Шаблон отображения данных: сложный запрос из сервисного уровня - PullRequest
7 голосов
/ 08 июля 2011

Я пою шаблон 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;
}

Мне кажется, я следую шаблону сопоставления данных этими методами ...


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

Я хочу выбрать лиц с каштановыми волосами И моложе 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;
}

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


Мой вопрос:

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

Ответы [ 2 ]

6 голосов
/ 08 июля 2011

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

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

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

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

1 голос
/ 24 декабря 2013

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

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;
}

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

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

...