Hello!
OK, I did some experimentation on this yesterday evening, and I think I have a clearer sense of at least part of the problem.
First thing I needed to find out is which listeners were actually firing when, so I wrote two very simple listeners (an event listener and a record listener), each implementations of Doctrine_Overloadable (see last part of
Creating a New Listener); they looked like this:
[code]
class My_Record_Listener_Tester extends Doctrine_Overloadable
{
public function __call($methodName, $args)
{
echo "Doctrine_Record_Listener::$methodName" . PHP_EOL;
}
}
// and then the same thing for Doctrine_EventListener
[/code]
I then wrote a simple CLI script to bootstrap my Doctrine manager and connection, attached these listeners as appropriate (Doctrine_Manager::addListener and Doctrine_Manager::addRecordListener), and ran the following test code:
[code]
echo "Running Doctrine_Connection::getTable('Post')..." . PHP_EOL;
$table = $conn->getTable('Post');
echo "...done." . PHP_EOL;
echo "Running Doctrine_Table::findAll()..." . PHP_EOL;
$records = $table->findAll();
echo "...done." . PHP_EOL;
[/code]
The first time I tried this, this is all that came out:
[output]
Running Doctrine_Connection::getTable('Post')...
...done.
Running Doctrine_Table::findAll()...
EventListener::preConnect
EventListener::postConnect
EventListener::preQuery
EventListener::postQuery
...done.
[/output]
Not a whole lot there to hook into; *Connect() won't help me, and the *Query() methods aren't really even documented. But I was wondering at this point, why in the world were none of the hydration hooks running? After all, I was getting back fully hydrated Post objects.
I took a closer look at my Post model at that point and realized that it's utilizing several built-in Doctrine templates ("actAs" stuff: timestampable, sluggable, etc.); since templates make heavy use of event and record listeners to do their work, I thought I'd test it without them attached, just to see if there were a conflict. Sure enough, when I ran the script again:
[output]
Running Doctrine_Connection::getTable('Post')...
...done.
Running Doctrine_Table::findAll()...
Record_Listener::getOption
Record_Listener::preDqlSelect
EventListener::preConnect
EventListener::postConnect
EventListener::preQuery
EventListener::postQuery
Record_Listener::getOption
Record_Listener::preHydrate
Record_Listener::getOption
Record_Listener::postHydrate
Record_Listener::getOption
Record_Listener::preHydrate
Record_Listener::getOption
Record_Listener::postHydrate
...done.
[/output]
Suddenly there are a whole slew of Record_Listener events firing that weren't firing when the actAs templates were still attached. That hydration sequence (getOption, preHydrate, getOption, postHydrate) fires once for every record returned…and there's also a getOption, preDqlSelect sequence that fires before the *Query() events.
Unfortunately, those actAs templates are pretty important, and so far I haven't found a way to get all those extra hooks to fire if _even one_ template is still attached to the model.
Do you know if this is a documented behavior? If so, is there a workaround?
I'm going to cross-post this in the Doctrine list too, since I think it may be useful information …either that, or I'm missing something obvious :)
Thanks!
Adam