Шаблон Data Mapper: сложный запрос из уровня сервиса

Я пою шаблон Data Mapper в Zend Framework. Пока это хорошо, но теперь я дошел до того, что мне нужна ваша помощь / мнение. Итак, давайте начнем с кода:

У нас есть таблица с несколькими людьми:

CREATE TABLE `persons` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `age` int(3) NOT NULL, `haircolor` varchar(20) DEFAULT NULL, PRIMARY KEY (`id``), ); 

Теперь я стараюсь выбирать всех людей, имеющих коричневые волосы. Я использую следующий метод в ServiceLayer

 public function getPeopleByHaircolor($hair) { return $this->getMapper()->fetch('haircolor = ?', $hair); } 

Метод в Mapper выглядит следующим образом:

 public function fetch($condition, $value) { $resultSet = $this->getTable()->fetchAll($this->getTable()->select()->where($cond, $value)); $entries = array(); foreach($resultSet as $row) { $entry = new Default_Model_Person(); $entry->id = $row->id; $entry->name = $row->name; [...] } return $entries; } 

Я думаю, что я следую шаблону Data Mapper с помощью этих методов …


Теперь проблема:

Я хочу выбрать Лица, у которых есть коричневые волосы И моложе 20 лет. Итак, как я могу это сделать? Моя попытка:

 public function getTeens($hair) { $rows = $this->getMapper()->fetch('haircolor = ?', $hair); $return = array(); foreach($rows as $row) { if((int)$row->age < 20) $return[] = $row; } return $return; } 

Но если вы получите больше переменных, например «люди с коричневыми волосами, моложе 20yrs и с именем« Foo Bar », мне нужно все больше и больше методов и / или foreach.


Мой вопрос:

Как вы это сделаете в шаблоне Data Mapper? Если я использую собственный SQL-запрос, например $ serviceLayer-> mapper-> table-> qry ('SELECT …'), это нарушает шаблон Data Mapper? Мне не нравятся эти дополнительные петли foreach, и мне кажется, что я делаю что-то неправильно, поэтому я написал этот вопрос.

Действительно, для двух условий нецелесообразно запрашивать одно условие, а затем фильтровать на другом, пока вы повторяете. Это не дает вам четкого подхода к более чем двум условиям. И реализация адаптеров разбиения на страницы становится довольно грязной.

Мне кажется, что проблема заключается в том, что метод mapper fetch() поддерживает только одно условие. Так:

  1. Измените подпись для поддержки множества условий.

  2. Кроме того, вы можете создать отдельный метод сопоставления для каждого метода расширенной выборки, например: fetchByHairAndAge($hair, $age) и т. Д.

В моем ограниченном опыте работы с картотеками данных я нашел следующий подход к работе достаточно хорошо для сценариев, с которыми я столкнулся до сих пор:

 public function getPeopleByHaircolorAndAge($haircolor, $age, $limit=null, $offset=null) { $people = new PersonCollection; $people->filterByHaircolor($haircolor); $people->filterByAge($age); $people->setLimit($limit); $people->setOffset($offset); $personCollectionMapper = new PersonCollectionMapper; $personCollectionMapper->fetch($people); return $people; } 

Сначала создавая экземпляр объекта домена, у меня есть возможность установить фильтры и другие переменные, которые может отобразить преобразователь данных из объекта, когда он вводится в устройство отображения.

Для меня это был превосходный подход до сих пор по сравнению с несколькими методами mapper, которые возвращают объект домена.