Er zijn veel manieren om dit aan te pakken, dit is er een van. Stel dat u een db-schema heeft dat lijkt op dit:
Nu kunt u AlbumMapper en ArtistMapper verantwoordelijk laten zijn voor het voor u ophalen van die objecten uit de 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);
}
Ik heb gezet dat AlbumMapper ArtistMapper vereist, dus met deze mapper worden albums altijd teruggestuurd met hun artiesten. Nu kan een voorbeeldimplementatie als volgt zijn, waarbij ik een kleine indexeringstruc gebruik om artiest aan albums toe te voegen:
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;
}
}
In dit geval zal uw album in de trant van:
class Album {
private $id;
private $title;
private $artists = array();
public function __construct($data) {
//initialize fields
}
public function addArtist(Artist $artist) {
$this->artists[] = $artist;
}
}
Aan het einde van dit alles zou je een verzameling Album-objecten moeten hebben die zijn geïnitialiseerd met hun artiesten.