Zend 1.11.6 and Doctrine 1.2

Recently, our project team spent quite some time figuring out a way to get Zend (ZF) working together with Doctrine ORM. Although there are a lot of howtos and guides out there it seems like everybody has his/her own way of merging these two frameworks.

In order to get most out of Doctrine one has to get the command line tool running, which provides a handy set of predefined functions to manage the underlying model schema. From what we’ve read so far there are major differences between Doctrine 1.2 and 2.x, especially when it comes to setting up the command line script. Again, although there are plenty of different approaches to get Zend working with Doctrine 2.x no ideal solution could be found so far…

For compatibility reasons we opted for Doctrine 1.2, as it seems much easier to get it working with ZF. Once the command line script (doctrine.php) was setup (which took quite some time, as the bootstrapping process needs to be tweaked a bit), the next step was to figure out a way to autoload Doctrine’s models using Zend’s bootstrapper.

As we are using a module based architecture and are keeping the models outside this module structure (in application/models) we needed a way to autoload the modules separately from the models, without running into the problem of loading anything twice (which would happen when using the default setup, i.e. Doctrine’s model loader together with Zend’s autoloader…).

Anyway, the solution was to use Zend’s module autoloader and use module bootstrap files on the one hand, and additionally use Doctrine’s modelsAutoload function via a callback:

public function _initDoctrine() {
  $this->getApplication()->getAutoloader()
                ->pushAutoloader(array('Doctrine', 'autoload'));

  spl_autoload_register(array('Doctrine', 'modelsAutoload'));

  $doctrineConfig = $this->getOption('doctrine');
  $manager = Doctrine_Manager::getInstance();
  $manager->setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
  $manager->setAttribute(Doctrine::ATTR_MODEL_LOADING, $doctrineConfig['model_autoloading']);
  $manager->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, $doctrineConfig['table_autoloading']);
  $manager->setAttribute(Doctrine::ATTR_DEFAULT_TABLE_CHARSET, 'utf8');

  //loading of Doctrine's models is done by Zend's autoloader -> @see _initAppAutoload
  //Doctrine_Core::loadModels($doctrineConfig['models_path']);

  $conn = Doctrine_Manager::connection($doctrineConfig['dsn'], 'doctrine');
  $conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
  $conn->setCharset('UTF8');
  return $conn;
}

The above code loads Doctrine and sets up the connection details. In order to bootstrap the modules use the following autoloader function:

protected function _initAppAutoload() {
        $moduleLoader = new Zend_Application_Module_Autoloader(array(
                    'namespace' => '',
                    'basePath' => dirname(__FILE__)));
}

This setup parses all of the applications script and models. This setup can also be used for Doctrine’s command line script (doctrine.php).

The settings used for Doctrine are shown in the following:

doctrine.cache = true
doctrine.dsn = "mysql://user@localhost/some_db"
doctrine.data_fixtures_path = APPLICATION_PATH "/configs/data/fixtures"
doctrine.sql_path = APPLICATION_PATH "/configs/data/sql"
doctrine.migrations_path = APPLICATION_PATH "/configs/migrations"
doctrine.yaml_schema_path = APPLICATION_PATH "/configs/schema.yml"
doctrine.models_path = APPLICATION_PATH "/models"

doctrine.generate_models_options.pearStyle = true
doctrine.generate_models_options.generateTableClasses = true
doctrine.generate_models_options.generateBaseClasses = true
doctrine.generate_models_options.baseClassPrefix = "Base_"
doctrine.generate_models_options.baseClassesDirectory =
doctrine.generate_models_options.classPrefixFiles = false
doctrine.generate_models_options.classPrefix = "Model_"

doctrine.table_autoloading = true

; Doctrine needs to use Aggressive autoloading for the CLI to generate prefixed models appropriately
; MODEL AUTOLOADING: 1 = aggressive, 2 = conservative
doctrine.model_autoloading = 2

[doctrineCLI : production ] 
doctrine.model_autoloading = 1

This setup shown above creates a Base folder inside the application/models folder and puts the auto-generated Doctrine models in there. We believe this setup is more convenient to use in comparison to put the base-model files in the core models folder too.

Additionally, the setup specifies that model-classes should be prefixed with “Model_” to make them more distinct from other Zend classes. Bear in mind that this approach comes with certain changes when using fixtures for instance, as you have to explicitely prefix model-class references.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *