Hi,
Hector Virgen wrote:
> We are taking a different approach that works well for us. When you look
> at methods like these:
>
> fetchLatestArticles()
> fetchArticlesBasedOnCategory($category)
> fetchBlueArticlesByOrderedByGermanyPaidLastMonth()
>
> They all have two things in common: they return articles and they rely
> on criteria.
*ACK*
> With that in mind, we have a single method in our mappers that can cover
> all of those cases:
>
> Default_Model_Mapper_Articles#fetchAll($criteria, $sort)
>
> The criteria is similar to a WHERE clause in SQL, but it's not in SQL
> format. It uses objects instead:
>
> $category = new Default_Model_Category();
> $category->setId(123);
> $mapper = new Default_Model_Articles_Mapper();
> $articles = $mapper->fetch(array(
> category => $category
> ));
>
> The mapper's fetch method then inspects the criteria array and maps it
> to a SQL WHERE clause. This includes adding any required joins:
>
> public function fetchAll(array $criteria = null, $sort = null)
> {
> $select = $this->getSelect();
> if (isset($criteria['category'])) {
> $select->where('category_id = ?', $criteria['category']->getId());
> }
> return $this->_createCollection($select, $sort);
> }
>
> The getSelect() method returns the bare bones select object for
> articles, where only the "id" is returned. The _createCollection()
> method takes the select object and fetches the result into a
> lazy-loading iterator.
But how do you deal with other properties? For example, your articles have a
"isPublished" flag.
Now you want a list with n articles, which are published (isPublished ===
1), ordered by another property "edited_on".
When I understand your solution correctly, it would require that you add all
possible criteria in your mapper, which can be used.
> [...]
> There are a lot of steps in this design but it helps to ensure that at
> any time you can swap out mappers or change your DB schema without
> having to rewrite a single line in the controllers. I actually used this
> design for one of our components and, half-way through, redesigned the
> entire schema for better performance. The only changes I had to make
> were in the mappers themselves.
> [...]
Every time you change your DB schema, you would need to change all your
mappers, to support the changed properties.
Keith's way with the repository would require now extra changes in the model
or the mapper, because the abstraction of the query makes it generic.
> Sometimes this mapping can get very complex, especially if you want to
> support lots of criteria. For these cases, I create a helper class whose
> only job it is to build that select query. It would be used internally
> by the mapper only, transparent from the controllers.
>
> public function fetch(array $criteria = null, $sort = null)
> {
> $search = new Default_Model_Mapper_Search_Articles($this);
> $search->setCriteria($criteria);
> $select = $search->getSelect();
> return $this->_createCollection($select, $sort);
> }
How does the mapper call it? Would your mapper expose a public method, which
will call this helper class?
--
Regards,
Thomas