Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Using HydratingResultSet and ObjectProperty’s Hydrator

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on September 5, 2013

zf2-zendframework2When joining table using Zend\Db, calling coloumn(s) in other table when make a join is a pain. It because if we use normal Zend\Db\ResultSet\ResultSet and setting up ArrayObjectPrototype with the class object, we only get the current model class only ( that consist of columns of single table). Register other table column on that class is NOT a solution, it will make a confusion on what entity is for. Maybe not best (errr…good) solution but simplest solution is to use Zend\Db\ResultSet\HydratingResultSet and Zend\Stdlib\Hydrator\ObjectProperty.
There is I explain on case situation : “we have a table named album ( with columns : `id`, `artist`, `title` ) and table named track ( with columns : `track_id`, `track_title`, and `album_id` as foreign key agains album )”.
Ok, let’s create model like as the docs :

//filename : module/Album/src/Album/Model/Album.php
namespace Album\Model;

class Album
{
    public $id;
    public $artist;
    public $title;

    public function exchangeArray($data)
    {
        $this->id     = (isset($data['id']))     ? $data['id']     : null;
        $this->artist = (isset($data['artist'])) ? $data['artist'] : null;
        $this->title  = (isset($data['title']))  ? $data['title']  : null;
    }

    public function getArrayCopy()
    {
        return get_object_vars($this);
    }
}

Ok, Let’s create a sample table class for album table :

//filename : module/Album/src/Album/Model/AlbumTable.php
namespace Album\Model;

use Zend\Db\TableGateway\TableGateway;

class AlbumTable
{
    protected $tableGateway;

    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }
    
   //to retrieve tableGateway object when needed.
    public function getTableGateway()
    {
        return $this->tableGateway;
    }

    public function JoinfetchAll()
    {
        $sqlSelect = $this->tableGateway->getSql()
                          ->select()
                          ->join('track', 'track.album_id = album.id', array('*'), 'left');

        return $this->tableGateway->selectWith($sqlSelect);
    }
}

If you want to reduce closure usage at your application, you can create factory for AlbumTable creation like the following :

//filename : module/Album/src/Album/Factory/Model/AlbumTableFactory.php
namespace Album\Factory\Model;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\TableGateway\TableGateway;
use Album\Model\AlbumTable;
use Album\Model\Album;

use Zend\Stdlib\Hydrator\ObjectProperty;
use Zend\Db\ResultSet\HydratingResultSet;

class AlbumTableFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $db = $serviceLocator->get('Zend\Db\Adapter\Adapter');

        $resultSetPrototype = new HydratingResultSet();
        $resultSetPrototype->setHydrator(new ObjectProperty());
        $resultSetPrototype->setObjectPrototype(new Album());

        $tableGateway       = new TableGateway('album', $db, null, $resultSetPrototype);
        $table              = new AlbumTable($tableGateway);

        return $table;
    }
}

and we just make a call like this :

//filename : module/Album/Module.php
namespace Album;

class Module
{
     // getAutoloaderConfig() and getConfig() methods here

     // Add this method:
     public function getServiceConfig()
     {
         return array(
             'factories' => array(
                 'Album\Model\AlbumTable' =>  'Album\Factory\Model\AlbumTableFactory'
             ),
         );
     }
 }

That’s it, we now can call like this :

$table = $this->getServiceLocator()->get('Album\Model\AlbumTable');
$joinedData = $table->JoinfetchAll();

foreach($joinedData as $row) {
    //$row->track_id will called even not registered
    //in album model class.
    echo $row->artist.' : '.$row->track_id; 
}

We know that we need to retrieve track table column form *JoinfetchAll()* table. but we don’t need to register it to be retrieve-able.

Ok, done, happy hacking ;)

About these ads

11 Responses

Subscribe to comments with RSS.

  1. Michael said, on September 5, 2013 at 9:34 am

    It’s nice to see your tutorial, i am working with HydratingResultSet and after i get the album entity, I want to save it so I pass to AlbumTable and it show message: track_id, track_title,album_id are not in the fileds list because Album(table database) consist only id, artist and title field.
    May you show me the best way to fix this issue, thanks !

  2. […] Abdul Malik Ikhsan: Using HydratingResultSet and ObjectProperty’s Hydrator […]

  3. Robert said, on September 22, 2013 at 3:09 pm

    Hello I tried your sample. I injected this code in index.phtml.
    $table = $this->getServiceLocator()->get(‘Album\Model\AlbumTable’);
    $joinedData = $table->JoinfetchAll();

    foreach($joinedData as $row) {
    //$row->track_id will called even not registered
    //in album model class.
    echo $row->artist.’ : ‘.$row->track_id;
    }
    i have an error

    get was unable to fetch or create an instance for getsServiceLocator.

    Could you giva nay help

  4. namjitharavind said, on November 26, 2013 at 8:31 pm

    Is there any way to see the $joinedData array_object as simple array rather than looping in for loop?

  5. JOSEPH said, on December 13, 2013 at 6:55 pm

    this is nice..reli worked for me…

  6. […] Zend Framework 2 : Using HydratingResultSet and ObjectProperty’s Hydrator […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 247 other followers

%d bloggers like this: