Jiew Meng
Jiew Meng

Reputation: 88187

Using Doctrine 2 with Zend Framework 1.10.x

how can i get started with Doctrine 2 + ZF? any tutorials or resources?

on a side note, i hear ZF2 will use Doctrine as its models, true?

Upvotes: 3

Views: 2315

Answers (2)

Christoph Strasen
Christoph Strasen

Reputation: 2752

I can give you some examples from the bootstrap.php I use:

    public function _initDoctrine() {
                if(PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) {
                    require_once('bootstrapDoctrine.inc.php');

                    //things below this line are for convenience        
                    require_once(dirname(__FILE__).'/../library/doctrinehelpers/requireEntitiesOnce.php');
                    Zend_Registry::set('doctrineEm', $em);
                    return $em;
                }
        }

And in the boostrapDoctrine.inc.php I have this:

use Doctrine\Common\ClassLoader,
    Doctrine\ORM\Configuration,
    Doctrine\ORM\EntityManager,
    Doctrine\Common\Cache\ArrayCache,
    Doctrine\DBAL\Logging\EchoSQLLogger;

    require_once(realpath(APPLICATION_PATH . '/../library').'/doctrine2/lib/Doctrine/Common/ClassLoader.php');

    $doctrineClassLoader = new ClassLoader('Doctrine', realpath(APPLICATION_PATH . '/../library').'/doctrine2/lib');
    $doctrineClassLoader->register();


    //no way to have your proxies generated in different directory per ZF module it seems so we use a global one
    $proxiesClassLoader = new ClassLoader('Proxies', realpath(APPLICATION_PATH . '/models/doctrineproxies'));
    $proxiesClassLoader->register();

    /*
     * @TODO make this step iterate over available modules
     */
        $driverImpl = $config->newDefaultAnnotationDriver(array(APPLICATION_PATH . '/modules/mymodule1/models/doctrineentities',APPLICATION_PATH . '/modules/mymodule2/models/doctrineentities'));
    $config->setMetadataDriverImpl($driverImpl);
    $config->setMetadataCacheImpl($cache);
    $config->setQueryCacheImpl($cache);

    // Proxy configuration
    $config->setProxyDir(realpath(APPLICATION_PATH . '/models/doctrineproxies'));
    $config->setProxyNamespace('Proxies');


    /**
     * this SQL logger is golden
         * @TODO implement a switch for verbose debugging
     */ 

     //   $logger = new Doctrine\DBAL\Logging\DebugStack();
     //   $config->setSQLLogger($logger);
     //   register_shutdown_function(function($logger) {
     //       echo '<pre>';
     //       print_r($logger->queries);
     //   }, $logger);


    $config->setAutoGenerateProxyClasses( true ); //disable in production environment

    $doctrineConfig = $this->getOption('resources'); //from ini
    $dbparams = $doctrineConfig['db']['params'];
    $connectionOptions = array(
         'driver'    => $doctrineConfig['db']['adapter'],
         'user'      => $dbparams['username'],
         'password'  => $dbparams['password'],
         'dbname'    => $dbparams['dbname'],
         'host'      => $dbparams['host']
    );
    $em = EntityManager::create($connectionOptions, $config); //stored in zend registry later

To allow the doctrine commandline tool to function I had to create a library/doctrine2/lib/cli-config.php which is also a stripped down zend framework bootstrap. This config has the disadvantage that I have to call the doctrine cli from within this directory. Works for me ;)

/*
* @TODO make the cli-tool more flexible by better path detection
*/
// Define path to application directory
defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    realpath(APPLICATION_PATH . '/../../include'),
    get_include_path(),
)));

/** Zend_Application */
require_once 'Zend/Application.php';

// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);


$    application->getBootstrap()->bootstrap('doctrine');
$em = $application->getBootstrap()->getResource('doctrine');

/*
$configuration = new \Doctrine\Common\Cli\Configuration();
$configuration->setAttribute('em', $em);
*/

$helperSet = new \Symfony\Components\Console\Helper\HelperSet(array(
    'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
    'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));

Now we are all hoping for a better doctrine integration but this will only happen in ZF 2 going a big step towards namespaces like doctrine did allready.

Hope I could help.

Upvotes: 2

Bryan M.
Bryan M.

Reputation: 17322

What's nice about working with ZF and Doctrine 2 is that there's very little that needs to be done to integrate them. Essentially, you just need access to an instance of Doctrine 2's EntityManager that's set up during the applications bootstrap, as well as make sure the Doctrine namespaces are getting loaded in your index.php (You'll need to use Doctrine's ClassLoader for this, Zend_Loader does not support namespaces yet).

You can instantiate your EntityManager manually in the bootstrap, or even easier, through a Resource Plugin (which makes it easy to store the database config in application.ini). You can pretty much follow the documentation on configuring and obtaining an Entity Manager in Doctrine's manual, and just have the init() method in your bootstrap resource return the instance.

You're probably going to want to depend highly on dependency injection for passing the EM to the various objects that need it. For an easy way to pass bootstrap resources into your action controllers, see this article on creating a simple resource injector.

I've been using Doctrine 2 with ZF since it's been in alpha, and have found it quite pleasant to work with.

Upvotes: 3

Related Questions