How to create a custom Doctrine2 hydrator with Symfony2

Doctrine2 allows you to create your own custom hydrators in case the stock ones do not provide the functionality that you require, Symfony2 provides an easy way to register your hydrators so you can use custom hydrators throughout your application.

You can read up on Doctrines hydrators in the official documentation, sometimes these may not fit your needs so you can create your own custom hydrators.

Imagine that you need to create an associative list style array of database results (eg. an ID indexed array of object names) for use in your application as opposed to an array of objects as you normally receive via a doctrine query, here is an example (a rather simple one) of a hydrator that will achieve this:

<?php 
namespace Your\Bundle\Hydrators;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
use PDO;

class ListHydrator extends AbstractHydrator 
{     
    protected function hydrateAllData()     
    {         
        $result = array();         
        $cache  = array();         
        foreach($this->_stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $this->hydrateRowData($row, $cache, $result);
        }

        return $result;
    }

    protected function hydrateRowData(array $row, array &$cache, array &$result)
    {
        if(count($row) == 0) {
            return false;
        }

        $keys = array_keys($row);

        // Assume first column is id field
        $id = $row[$keys[0]];

        $value = false;

        if(count($row) == 2) {
            // If only one more field assume that this is the value field
            $value = $row[$keys[1]];
        } else {
            // Remove ID field and add remaining fields as value array
            array_shift($row);
            $value = $row;
        }

        $result[$id] = $value;
    }
}

This hydrator is pretty straightforward, it examines the columns returned in each row of the resultset, if there are only two columns, the first is assumed to be the key field (which would normally be the objects ID) and the second is assumed to be the value field. If there are more than two columns per row then the returned array will be an ID indexed array with each row consisting of an array of the remaining column values.

Now that we have a custom hydrator we need to register it using Symfony’s configuration system, this is pretty straight forward and can be achieved like so within your applications config.yml:

orm:
     entity_managers:
       default:
         mappings: ~
         hydrators:
             ListHydrator: \Your\Bundle\Hydrators\ListHydrator

You can register any number of customer hydrators in this fashion.

To use your custom hydrator you simply specify it’s name as an argument to Doctrine’s getResult function like so:

$results = $this->getDoctrine()->getManager()->createQuery('{query}')->getResult('ListHydrator');

That’s it, you can now create as many custom hydrators as you’d like.