datamapper 디자인 패턴을 이해하는 데 문제가 있습니다. 나는 두 가지 질문을한다. 하나는 앨범을 얻고 다른 하나는 아티스트를 얻는다. 앨범과 아티스트 (밴드 멤버) 목록을 만들고 싶습니다. 이 둘 사이에는 일대일 관계가 있습니다.SQL 쿼리에서 데이터 매퍼를 사용하는 방법
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,
));
}
많은 감사
매트
코드를 근본적으로 변경하고 앨범 + 아티스트 정보를 단일 쿼리로 가져 오기 위해 'join'쿼리를 수행해야합니다. –
그럼 내 foreach 앨범에 중복되지 않을까요? 나는 각 앨범을 한 번 울리며, 앨범 밑에있는 앨범을 되풀이하는 아티스트가 있다면 그 앨범을 되풀이하고 싶다. 그래서 여러 번 quires (나는 정보를 복제하고 싶지 않다)가있다. 앨범마다 아티스트 (밴드 멤버)가 여러 명 있습니다. – Matt