Hydrators are used when ever you need to get data in or out of an object/entity, which can be when using a form, or also when saving or loading an entity from storage.
I wouldn't use the Hydrator to populate your objects with related objects (e.g. for adding an antist object to your album). I would leave this upto your services / mappers.
Here's an example how I'd do it:
Album.php
<?php
class Album
{
// .. properties / getters/setters etc ..
public function setArtist(ArtistInterface $artist)
{
$this->artist = $artist;
}
public function getArtist()
{
return $this->artist;
}
}
AlbumHydrator.php
this can vary, you would use getters/setters or properties, take a look at the base hydrators to decide which route you want to take..
Your Hydrator will take the Assembled objects, and give back the data you would need to either show a form, or save to persistence etc.
<?php
class AlbumHydrator // extends Zend\Stdlib\Hydrator\ClassMethods
{
public function extract($object)
{
return array(
'artist_id' => $object->getArtist()->getId(),
'albumn_name' => $object->getAlbumName()
)
}
// .. etc
}
AlbumService.php
<?php
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
class AlbumService implements ServiceManagerAwareInterface
{
/**
* Get an album, we'll also load any related objects here
*
* @param int
*/
public function find($id)
{
$album = $this->_getAlbumMapper()->find($id);
$artist = $this->_getArtistMapper()->findByAlbum($id);
$album->setArtist($artist);
return $album;
}
/**
* Get the Mapper
*
* @return Application\Mappers\AlbumMapper
*/
protected function _getAlbumMapper()
{
return $this->getServiceManager()
->get('AlbumMapper')
;
}
// ..
}
You would setup your service in the Service Manager config like this:
'AlbumService' => function($sm) {
$mapper = $sm->get('AlbumMapper');
$service = new Application\Service\AlbumService();
$service->setAlbumMapper($mapper);
return $service;
},
You then use your service to create the object graph you need. You would have separate mappers for each of the entities, and the services can use the mappers to generate the objects you require.
You would usually have a Hydrator for each of the entities, and the mappers would use those to populate the objects for you. This would depend on your implementation, you may well be using TableGateway or something instead of the mappers, which would still work ok.
An example now of accessing your objects when inside your controller
SomeController.php
public function albumAction()
{
$id = (int) $this->params()->fromRoute('id', FALSE);
if( ! $id) {
// do something with errors etc ..
return $this->redirect()->toRoute('default_route', array(
'controller' => 'index',
'action' => 'index'
));
}
$request = $this->getRequest();
$album = $this->getServiceLocator()->get('AlbumService')->find($id);
$artistName = $album->getArtist()->getName();
return new ViewMdoel(
'album' => $ablum,
'artistName' => $artistName
);
}
Populating object graphs when using collections is a little more tricky, but I would tend to use lazy loading and virtual proxies for that kind of setup, which will basically defer loading the objects you need until you require them, check these out:
http://phpmaster.com/intro-to-virtual-proxies-1/
http://phpmaster.com/intro-to-virtual-proxies-2/