Deprecated Behaviour

The inane, sometimes insane, ramblings from the mind of Brenton Alker.

Bootstrapping the Doctrine 2.0 Autoloader in Zend Framework

Please Note: This post was based on the Alpha release of Doctrine2. They have since added Doctrine\Common\IsolatedClassLoader which (among other things) doesn’t automatically register itself so we no longer have to unregister it, making things much easier.

Doctrine 2.0 looks like it might finally be the ORM framework I have been seeking for PHP. While the older versions of Doctrine provided great functionality, they were too intrusive for my taste. I think an ORM should provide a true data mapper; in which the domain entities need know nothing about their persistence.

Matthew Weier O’Phinney has already posted about autoloading Doctrine in Zend Framework, but Doctrine2 presents some new challenges. Mainly that Doctrine2 is fully PHP5.3, including “real” namespaces, so its classes don’t follow the (current) Zend naming standard and the ZF autoloader won’t load them for us.

Good News, Doctrine provides its own autoloader that we can leverage to load its own classes.

Bad News, the Doctrine autoloader automatically registers itself with spl_autoload_register, causing the normal Zend loader to be forgotten (well, pushed down the stack, where it isn’t very useful).

Good News, it’s easy to remove the doctrine autoloader using spl_autoload_unregister, then push it onto the ZF autoloader stack, targeting the Doctrine namespace. Letting the ZF autoloader call it as necessary.

Enough jibber-jabber, how do we do all this? In the bootstrap! Adding this method to your Bootstrap.php will achieve what we want; adding the Doctrine autoloader to the Zend Framework autoloader queue for the “Doctrine\” namespace.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    protected function _initDoctrine()
    {
        // Create the doctrine autoloader and remove it from the spl autoload stack (it adds itself)
        require_once 'Doctrine/Common/ClassLoader.php';
        $doctrineAutoloader = array(new \Doctrine\Common\ClassLoader(), 'loadClass');
        spl_autoload_unregister($doctrineAutoloader);

        // Fetch the global Zend Autoloader
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Push the doctrine autoloader to load for the Doctrine\ namespace
        $autoloader->pushAutoloader($doctrineAutoloader, 'Doctrine\\');
    }

We can use all of Doctrine’s classes anywhere else in our code.

1
2
3
4
<?php
use Doctrine\ORM;
$manager = EntityManager::create(array('driver' => 'pdo_sqlite', 'path' => ':memory:/'));
// ...

I still have a lot to learn and the documentation on 2.0 is a little sparse as yet, but this is a start.