Zend Framework and Doctrine integration – autoloading of doctrine models

I’m reinvestigating Doctrine and Zend Framework for a new project.  I’d dismissed them last year as not meeting my needs, but am giving it another go this year.  I have to say I’ve got mixed impressions at best, as there seems to be little in the way of documentation with real use cases.

I would have expected there to be some explicit reference to how to set this up, but the best I can find are general examples where the Doctrine models directories are appended to the include_path in a ZF index file.  Shouldn’t there be a way to explicitly have the Doctrine subsystem react to requests for models as well?

I was expecting the Doctrine::autoload to look for the classes on the ‘models path’ set via Doctrine::setModelsDirectory() call, but it doesn’t.

Hrm… after more investigation, it seems there’s a ‘modelsAutoload’ method on the Doctrine_core which will automatically look at the models_path set via setModelsDirectory().  Almost what I need.  Except…(!)

There’s no support for multiple directories.  The standard Doctrine generation process creates a ‘BaseFoo’ object in a ‘generated’ directory below where the standard ‘Foo’ file is written.  The ‘Foo’ file subclasses the BaseFoo, but there’s no support to have it autoloaded.

In my ‘_initDoctrine()’ in Bootstrap, I’ve got

$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader(array('Doctrine','modelsAutoload'));

I know what to do here! I thought to myself. I’ll subclass Doctrine’s Core (which is what’s referenced by the ‘Doctrine’ above) and have that be the autoloader to use.  I’ll modify the modelsAutoload() method to deal with an array of $_modelsDirectory entries, and attempt to load from each of them.  Except…(!)

$_modelsDirectory is *private*.  I can’t modify it in a subclass, nor is there a get() method on the Core class to access it.  There’s a *set* method (setModelsDirectory()) but no get!  So, I’m rather forced to go through modifying the Doctrine Core to get the behaviour I want, in the simplest form.  I’ve been trying to followup on some other postings about getting autoload to work with Doctrine-generated models, but they seem incomplete (to me anyway) or suggest to modify how Doctrine generates its class names (doesn’t seem simple or straightforward to me at all).  Having Doctrine core be able to deal with an array of paths to check for models would be the simplest, especially given that Doctrine *forces* this issue on you by generating classes in different directories by default.

Crux of the code is:

Doctrine/Core.php line 1142

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(is_array(self::$_modelsDirectory)) {
 foreach(self::$_modelsDirectory as $dir) {
  $class = $dir . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
  if (file_exists($class)) {
   require $class;
   return true;
  }
 }
} else {
 $class = self::$_modelsDirectory . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
 if (file_exists($class)) {
  require $class;
  return true;
 }
}

I don’t see Doctrine code on github – if it’s there I’ll fork it and create my own patched version for a pull.

So now in my code, I can say

Doctrine::setModelsDirectory(array("/app/doctrine/models/","/app/doctrine/models/generated/"));

FWIW, I can’t find the equivalent code section in Doctrine 2.0, though I suspect this might still be a design issue in 2.0 (would love to be proved wrong on that).

How have *you* dealt with autoloading of Doctrine-generated classes in ZF (or indeed, in general)?


I'm currently working on a book for web freelancers, covering everything you need to know to get started or just get better. Want to stay updated? Sign up for my mailing list to get updates when the book is ready to be released!

Web Developer Freelancing Handbook

Be Sociable, Share!

Leave a Reply