views:

293

answers:

2

I can't find a way to set the default hydrator in Doctrine. It should be available. Right?

http://www.doctrine-project.org/documentation/manual/1_2/en/data-hydrators#writing-hydration-method

The above documentation page explains how to create a custom hydrator. The drawback here is that you need to "specify" the hydrator each and every time you execute a query.

Please help. Thank you.

-- Mario Awad

A: 

Mario,

That'd be a great idea, and on reading your question I thought it'd be something you could do via Doctrine. However, reading through the code makes me think you can't:

Doctrine_Query::create() creates a new query specifying only the first argument of Doctrine_Query_Abstract::__construct(), the connection, without specifying the second argument - the hydration mode. No calls to configuration are made. As no hydrator is passed, a new Doctrine_Hydrator is created, and its constructor equally does not look anywhere for a configuration option, and thus it has the default Doctrine::HYDRATE_RECORD setting.

Perhaps subclassing Doctrine_Query with the below factory method is the easiest option?

public static function create($conn = null)
{
    return new Doctrine_Query($conn,Doctrine::HYDRATE_ARRAY);
}
timruffles
Hi Tim, thank you for the answer. Your idea will work if there's a way to tell Doctrine to use our custom Query class by default. Any ideas if such a feature exists? Thanks again.
Mario Awad
There should be a way to set the doctrine query class. $conn->setAttribute(Doctrine_Core::ATTR_QUERY_CLASS, 'MyQueryClass'); - This is from the Doctrine 1.2 documentation http://www.doctrine-project.org/projects/orm/1.2/docs/manual/configuration/en
Chris Gutierrez
+1  A: 

I figured this out by reading Chris Gutierrez's comment and changing some stuff.

First, define an extension class for Doctrine_Query. Extend the constructor to define your own hydration mode.

class App_Doctrine_Query extends Doctrine_Query
{
    public function __construct(Doctrine_Connection $connection = null,
        Doctrine_Hydrator_Abstract $hydrator = null)
    {
        parent::__construct($connection, $hydrator);
        if ($hydrator === null) {
            $this->setHydrationMode(Doctrine::HYDRATE_ARRAY); // I use this one the most
        }
    }
}

Then, in your bootstrap, tell Doctrine about your new class.

Doctrine_Manager::getInstance()->setAttribute(Doctrine_Core::ATTR_QUERY_CLASS, 'App_Doctrine_Query');  

Chris Gutierrez defined the attribute for the connection instead of globally but I have more than one connection and I want to use this default for all of them.

Now you don't have to call Doctrine_Query::setHydrationMode() every time you build a query.

Here's more information
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/configuration/en#configure-query-class

EDIT: Changes below

I have found a problem with the above. Specifically, doing something like "Doctrine_Core::getTable('Model')->find(1)" will always return a hydrated array, not an object. So I have altered this a bit, defining custom execute methods for use in a Query call.

Also, I added memory freeing code.

class App_Doctrine_Query extends Doctrine_Query
{
    public function rows($params = array(), $hydrationMode = null)
    {
        if ($hydrationMode === null)
            $hydrationMode = Doctrine_Core::HYDRATE_ARRAY;
        $results = parent::execute($params, $hydrationMode);
        $this->free(true);
        return $results;
    }

    public function row($params = array(), $hydrationMode = null)
    {
        if ($hydrationMode === null)
            $hydrationMode = Doctrine_Core::HYDRATE_ARRAY;
        $results = parent::fetchOne($params, $hydrationMode);
        $this->free(true);
        return $results;
    }
}
mattalexx