Intereting Posts
отображать данные из базы данных в раскрывающийся список CodeIgniter Как остановить скрипт PHP, работающий на фоне Преимущества Secury PHP PDO vs mysql _ * () Недопустимые аргументы в php Как добавить метод к существующему классу в PHP? Как получить объект запроса POST, используя Slim framwork Запись в определенную строку в PHP Передача пользовательских входных данных с html на php-страницу и отображение содержимого на html-странице без перезагрузки переменные, передающие ничего, показывают неопределенную ошибку переменной, поэтому вы хотите поместить значение по умолчанию для переменной как получить платежную информацию о Magento? PHP – filesize () возвращает пустую строку Сканеры штрих-кода Как загрузить файл на сервер с помощью HTTP POST multipart / form-data Какое регулярное выражение используется для преобразования этой строки в массив? php wordpress password change – внесите меня в журнал!

Как использовать преобразователь данных с sql-запросами

У меня возникли проблемы с пониманием шаблона проектирования datamapper. У меня есть два запроса (один для получения альбомов и один для создания исполнителя). Я хочу составить список альбомов и исполнителей (участников группы). Между ними существует одно-много отношений.

Запросы SQL

public function getArtist() { $adapter = $this->getAdapter(); $sql = new Sql($adapter); $select = $sql->select(); $select->from('genre'); $select->where(array( 'album_id' => $album,)); $selectString = $sql->getSqlStringForSqlObject($select); $resultSet = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); return $resultSet; } public function getAlbum() { $adapter = $this->getAdapter(); $sql = new Sql($adapter); $select = $sql->select(); $select->from('album'); $selectString = $sql->getSqlStringForSqlObject($select); $resultSet = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); return $resultSet; } 

Когда я делаю что-то похожее ниже, я заканчиваю запуск отдельного запроса для каждого альбома. Я не хочу этого делать. Как мне настроить что-то подобное на http://akrabat.com/php/objects-in-the-model-layer-part-2/ ? Могу ли я настроить так, чтобы каждый объект представлял запрос (я хотел бы использовать объединения в своих запросах, а не для создания сущности для каждой таблицы)?

  <?php foreach ($albums->getAlbum() as $album) : ?> <tr> <td><?php echo $this->escapeHtml($album->id);?></td> <td><?php echo $this->escapeHtml($album->title);?></td> <td><?php echo $this->escapeHtml($album->artist);?></td> <td> <?php foreach ($albums->getArtist($album->id) as $member) : ?> 

Использование решения, приведенного ниже

ConcreteAlbumMapper.php

 use Zend\Db\Adapter\AdapterInterface; use Album\Model\AlbumMapper; namespace Album\Model; class ConcreteAlbumMapper implements AlbumMapper { public function __construct(AdapterInterface $dbAdapter) { $this->adapter =$dbAdapter; } public function fetchAlbums(ArtistMapper $artistMapper) { $adapter = $this->getAdapter(); $sql = new Sql($adapter); $select = $sql->select(); $select->from('album'); $selectString = $sql->getSqlStringForSqlObject($select); $albumRows = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); $albums = array(); foreach ($albumRows as $albumRow) { $albums[$albumRow['id']] = new Album($albumRow); } $artists = $artistMapper->fetchByAlbumIds(array_keys($albums)); //marrying album and artists foreach ($artists as $artist) { /** * not crazy about the getAlbumId() part, would be better to say * $artist->attachYourselfToAnAlbumFromThisIndexedCollection($albums); * but going with this for simplicity */ $albums[$artist->getAlbumId()]->addArtist($artist); } return $albums; } } 

ConcreteMemberMapper.php

 <?php namespace Album\Model; use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Sql\Sql; use Album\Model\Member; class ConcreteMemberMapper { public function __construct(AdapterInterface $dbAdapter) { $this->adapter =$dbAdapter; } public function getAdapter() { if (!$this->adapter) { $sm = $this->getServiceLocator(); $this->adapter = $sm->get('Zend\Db\Adapter\Adapter'); } return $this->adapter; } public function fetchByAlbumIds($ids) { $adapter = $this->getAdapter(); $sql = new Sql($adapter); $select = $sql->select(); $select->from('members'); $select->where(array( 'album_id' => $ids)); $selectString = $sql->getSqlStringForSqlObject($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); return $results; //return \Zend\Stdlib\ArrayUtils::iteratorToArray($results); } public function getAlbumId() { return $this->albumId; } } 

Album.php

 <?php namespace Album\Model; use Zend\InputFilter\InputFilter; use Zend\InputFilter\InputFilterAwareInterface; use Zend\InputFilter\InputFilterInterface; class Album //implements InputFilterAwareInterface { public $id; public $title; public $artist; public $members = array(); public function __construct($data) { $this->id = (!empty($data['id'])) ? $data['id'] : null; $this->artist = (!empty($data['artist'])) ? $data['artist'] : null; $this->title = (!empty($data['title'])) ? $data['title'] : null; $this->members = (!empty($data['members'])) ? $data['members'] : null; } public function addMember(Member $member) { $this->members[] = $member; } 

AlbumController.php

  public function indexAction() { $dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'); //$album = new Album(); $albumMapper = new ConcreteAlbumMapper($dbAdapter); $memberMapper = new ConcreteMemberMapper($dbAdapter); $bar=$albumMapper->fetchAlbums($memberMapper); //$artistMapper = new //var_dump($bar); return new ViewModel(array( 'albums' => $bar, )); } 

Большое спасибо
Matt

Есть много способов приблизиться к этому, это один из них. Допустим, у вас есть схема db, подобная этому:

введите описание изображения здесь

Теперь вы можете иметь AlbumMapper и ArtistMapper для получения этих объектов из db для вас:

 interface AlbumMapper { /** * Fetches the albums from the db based on criteria * @param type $albumCriteria * @param ArtistMapper $artistMapper * * Note: the ArtistMapper here can be also made optional depends on your app */ public function fetchBySomeCriteria($albumCriteria, ArtistMapper $artistMapper); } interface ArtistMapper { /** * @param array $ids * @return Artist[] */ public function fetchByAlbumIds(array $ids); } 

Я добавил, что AlbumMapper требует ArtistMapper, поэтому с этим картографом Альбомы всегда возвращаются вместе со своими художниками. Теперь пример реализации может быть таким, когда я использую небольшой индексный трюк, чтобы привязать исполнителя к альбомам:

 class ConcreteAlbumMapper implements AlbumMapper { public function fetchBySomeCriteria($albumCriteria, ArtistMapper $artistMapper) { //sql for fetching rows from album table based on album criteria $albums = array(); foreach ($albumRows as $albumRow) { $albums[$albumRow['id']] = new Album($albumRow); } $artists = $artistMapper->fetchByAlbumIds(array_keys($albums)); //marrying album and artists foreach ($artists as $artist) { /** * not crazy about the getAlbumId() part, would be better to say * $artist->attachYourselfToAnAlbumFromThisIndexedCollection($albums); * but going with this for simplicity */ $albums[$artist->getAlbumId()]->addArtist($artist); } return $albums; } } 

В этом случае ваш Альбом будет выглядеть следующим образом:

 class Album { private $id; private $title; private $artists = array(); public function __construct($data) { //initialize fields } public function addArtist(Artist $artist) { $this->artists[] = $artist; } } 

В конце этого вы должны иметь коллекцию объектов альбома, инициализированных их Художниками.