Doctrine ORM as model layer for Zend Framework

In my opening post, I mentioned a new project that I’m working on which is a fairly simple web application with a few database tables for user management and the usual stuff. It’s exact nature and purpose is not important here.

Anyway, I had worked with Zend Framework before and while it’s an awesome application framework, the database abstraction provided by the Zend_Db classes never quite satisfied me.

Some time ago I came across Doctrine, an object relational mapper (ORM) for PHP. What it does is pretty cool: It lets you define a database schema by either writing a markup of it in YAML, which is really straight forward and simple, or writing a set of PHP classes that represent your database tables and their relations like one-to-many, many-to-many and so on. Both variants contain the exact same information. It’s just a matter of personal taste which one you prefer. I chose the YAML format because I like such things contained and small.

After defining a schema, Doctrine generates the database tables and the corresponding PHP classes (if you wrote YAML) and provides you with an object oriented interface to your database. You no longer read result sets of rows or simple data containing object anymore. Instead you can fetch objects from your database that are aware of their relations to other classes and provide the necessary logic to ensure data integrity and allow you to fetch any objects that are related by calling appropriate methods of these objects.

But I wanted to tell you how to integrate Doctrines magic into the Zend Framework. Since Doctrine comes with its own autoloader, you’ll encounter conflicts with Zend_Loader_Autoloader. After messing around with it for a while, I found a solutions that works without any nasty hard coded require_once calls. Just add this method to your bootstrapper:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initAutoload()
    {
        $loader = Zend_Loader_Autoloader::getInstance();
        //Doctrine Namespace without trailing "_" to load the base Doctrine class
        $loader->registerNamespace('Doctrine');
        //Autoloader for Doctrine classes
        $loader->pushAutoloader(array('Doctrine', 'autoload'));
        //Autoloader for Doctrines generated models
        $loader->pushAutoloader(array('Doctrine', 'modelsAutoload'));
    }
}

But what does it do?

Well, by registering the namespace “Doctrine” (Yes, without the trailing “_”), we tell ZF that there is a class called “Doctrine” on the include path. ZF will load Doctrine.php when that class is first needed.

After that we register two additional autoloaders:

  • Doctrine::autoload() for Doctrines own classes like Doctrine_Core or Doctrine_Query. Again, we omit the trailing “_” because Doctrine adds these by itself.
  • Doctrine::modelsAutoload() for the generated (or user written) model classes that probably won’t reside on the include path. Without this line, Doctrine will not be able to find it’s model classes and will die in a fatal error as soon as you try to access your database. Doctrine::autoload() alone will NOT load models!

Voilà! You have a working Doctrine model layer and a bunch of problems less. You will see that Doctrine plays really well with Zend Framework once these initial problems are solved.

  1. techpriester posted this