Zend Framework 1.11 and Doctrine 2.2.x integration

Quickly integrate Doctrine 2.2.x (used 2.2.1) into Zend Framework 1.11:

I will assume you have a working installation of Zend Framework. If not, go to Zend Framework “getting started” and create a project, then continue here.

  1. Download Doctrine (http://www.doctrine-project.org/projects/orm.html) and copy contents of Doctrine folder into

    /library
    

    Copy contents of Doctrine’s bin folder into ZF bin folder. (doctrine, doctrine.bat and doctrine.php)

  2. Edit the Bootsraping file:

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        /**
         * generate registry
         * @return Zend_Registry
         */
        protected function _initRegistry(){
            $registry = Zend_Registry::getInstance();
            return $registry;
        }
    
        /**
         * Register namespace Default_
         * @return Zend_Application_Module_Autoloader
         */
        protected function _initAutoload()
        {
            $autoloader = new Zend_Application_Module_Autoloader(array(
                'namespace' => 'Default_',
                'basePath'  => dirname(__FILE__),
            ));
            return $autoloader;
        }
    
        /**
         * Initialize Doctrine
         * @return Doctrine_Manager
         */
        public function _initDoctrine() {
            // include and register Doctrine's class loader
            require_once('Doctrine/Common/ClassLoader.php');
            $classLoader = new \Doctrine\Common\ClassLoader(
                'Doctrine',
                APPLICATION_PATH . '/../library/'
            );
            $classLoader->register();
    
            // create the Doctrine configuration
            $config = new \Doctrine\ORM\Configuration();
    
            // setting the cache ( to ArrayCache. Take a look at
            // the Doctrine manual for different options ! )
            $cache = new \Doctrine\Common\Cache\ArrayCache;
            $config->setMetadataCacheImpl($cache);
            $config->setQueryCacheImpl($cache);
    
            // choosing the driver for our database schema
            // we'll use annotations
            $driver = $config->newDefaultAnnotationDriver(
                APPLICATION_PATH . '/models'
            );
            $config->setMetadataDriverImpl($driver);
    
            // set the proxy dir and set some options
            $config->setProxyDir(APPLICATION_PATH . '/models/Proxies');
            $config->setAutoGenerateProxyClasses(true);
            $config->setProxyNamespace('App\Proxies');
    
            // now create the entity manager and use the connection
            // settings we defined in our application.ini
            $connectionSettings = $this->getOption('doctrine');
            $conn = array(
                'driver'    => $connectionSettings['conn']['driv'],
                'user'      => $connectionSettings['conn']['user'],
                'password'  => $connectionSettings['conn']['pass'],
                'dbname'    => $connectionSettings['conn']['dbname'],
                'host'      => $connectionSettings['conn']['host']
            );
            $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);
    
            // push the entity manager into our registry for later use
            $registry = Zend_Registry::getInstance();
            $registry->entitymanager = $entityManager;
    
            return $entityManager;
        }
    
    }
    
  3. Edit application/configs/application.ini and add the database configuration (MySQL database in this case, will be different if you are using another option):

    doctrine.conn.host = '127.0.0.1'
    doctrine.conn.user = 'root'
    doctrine.conn.pass = ''
    doctrine.conn.driv = 'pdo_mysql'
    doctrine.conn.dbname = 'databasename'
    doctrine.path.models = APPLICATION_PATH "/models"
    
  4. Edit doctrine.php and put this contents:

    define('APPLICATION_ENV', 'development');
    
    define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
    
    set_include_path(implode(PATH_SEPARATOR, array(
        realpath(APPLICATION_PATH . '/../library'),
        get_include_path(),
    )));
    
    // Doctrine and Symfony Classes
    require_once 'Doctrine/Common/ClassLoader.php';
    $classLoader = new \Doctrine\Common\ClassLoader('Doctrine', APPLICATION_PATH . '/../library');
    $classLoader->register();
    $classLoader = new \Doctrine\Common\ClassLoader('Symfony', APPLICATION_PATH . '/../library/Doctrine');
    $classLoader->register();
    $classLoader = new \Doctrine\Common\ClassLoader('Entities', APPLICATION_PATH . '/models');
    $classLoader->setNamespaceSeparator('_');
    $classLoader->register();
    
    // Zend Components
    require_once 'Zend/Application.php';
    
    // Create application
    $application = new Zend_Application(
        APPLICATION_ENV,
        APPLICATION_PATH . '/configs/application.ini'
    );
    
    // bootstrap doctrine
    $application->getBootstrap()->bootstrap('doctrine');
    $em = $application->getBootstrap()->getResource('doctrine');
    
    // generate the Doctrine HelperSet
    $helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
        'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
        'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
    ));
    
    \Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
    
  5. Now you can execute Doctrine’s from CLI and test that the correct version appears and that is functional:

    php doctrine.php 
    
  6. Now let’s create database tables from entities. Let’s create an entity, then execute doctrine command to create database table: Create application/models/User.php
    /**
     * @Entity
     * @Table(name="users")
     */
    class Default_Model_User
    {
        /**
         * @Id @Column(type="integer")
         * @GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /** @Column(type="string") */
        private $name;
    
        public function setName($string) {
            $this->name = $string;
            return true;
        }
    }
    

    Then, execute the command from CLI:

    php doctrine.php orm:schema-tool:create
    

    This should have created the table users with the two columns configured in our model’s annotations.

    If you want to see the SQL executed to accomplish this, execute:

    php doctrine.php orm:schema-tool:create –dump-sql
    

    To learn more about doctrine cli interface, refer to http://readthedocs.org/docs/doctrine-orm/en/latest/reference/tools.html#command-overview

  7. Now we can execute some code in a controller to test that we can persist data using doctrine:

    Edit a controller and add:

    First, in the controller we need to get Doctrine’s Entity Manager, we can avoid repeationg this code initializing the controller like:

    public function init()
        {
            /* Initialize action controller here */
            $registry = Zend_Registry::getInstance();
            $this->_em = $registry->entitymanager;
    
        }
    

    Then, creating an action (will use indexAction from IndexController to show it:

    public function indexAction()
    {
    $testEntity = new Default_Model_User;
    $testEntity->setName('Hector Pinol');
    $this->_em->persist($testEntity);
    $this->_em->flush();
    }
    

    So now call this action from a browser and we should have a row in DB with name “Hector Pinol” !

    Note that No data is actually persisted until we call “flush” method. Doctrine runs all “persisted” objects as a transaction when we call this method.

19 thoughts on “Zend Framework 1.11 and Doctrine 2.2.x integration

  1. Congratulations ! It worked in 5 minutes. I spent hours trying with various advices… Thank you very very much !
    And as you seem to be an expert in the field, what would be the best free tool to draw the model and then generate the classes from that visual model.

    • You can do this with Doctrine itself, I’ll try to update the post or write another on how to reverse engineer the database, but to get you started, once you can execute doctrine from the CLI, you do something like: “php doctrine orm:convert-mapping –from-database annotation . ” and it will generate the entities in the directory where you are (change the dot for a route and it will generate them there)

  2. Pingback: Aus den Blogs: Zend Framework und Doctrine, Capistrano, CRUD, NetBeans, Magento, WordPress, Restful - Zend Framework Magazin

  3. Pingback: Zend Framework and Doctrine 2 integration. « Codeperl's Knowledge Sharing System

  4. Hey there,
    Thanks for your great tuto! I’m new to ZF and I managed to generate the table using the CLI command, so I’m almost there.
    However there’s something wrong with the bootstrap on my local server (WAMP): The website won’t work anymore, I’ve got an HTTP error 500.
    I’ve located the problem, it appears on line 69:
    $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);

    I know I’m not far. Do you have an idea how I could fix this bug?
    Thanks :)

    • some problem connecting to the database I guess. If you have located the error there, go deep and enter the create function in doctrine’s code to debug it and see when exactly is the function giving the problem.

  5. Can u help me please I have this error and I can’t resolve it .
    Parse error: syntax error, unexpected T_REQUIRE_ONCE in C:\wamp\www\library\doctrine……

    Thanks in advance .

  6. hello Hector,

    I followed the instructions above. It’s not till I execute this: “php doctrine.php ” in the command line when I get an error stating “could not open input file: doctrine.php”

    I appreciate any help you can provideme. I’m new at this and struggling here.

    Charlie

      • appreciate for the response Hector.

        I did what you said. I set the command line in the directory where the ZF Bin folder is. Now, I get another error. I would really be thankful if you can help me locate the source of it:
        /**************************************************************

        PHP Warning: require_once(Doctrine/Common/ClassLoader.php): failed to open stream: No such file or directory in C:\wamp
        \bin\php\zen_framework\bin\doctrine.php on line 30
        PHP Stack trace:
        PHP 1. {main}() C:\wamp\bin\php\zen_framework\bin\doctrine.php:0

        Warning: require_once(Doctrine/Common/ClassLoader.php): failed to open stream: No such file or directory in C:\wamp\bin\
        php\zen_framework\bin\doctrine.php on line 30

        Call Stack:
        0.0008 241672 1. {main}() C:\wamp\bin\php\zen_framework\bin\doctrine.php:0

        PHP Fatal error: require_once(): Failed opening required ‘Doctrine/Common/ClassLoader.php’ (include_path=’;.;C:\php\pea
        r’) in C:\wamp\bin\php\zen_framework\bin\doctrine.php on line 30
        PHP Stack trace:
        PHP 1. {main}() C:\wamp\bin\php\zen_framework\bin\doctrine.php:0

        Fatal error: require_once(): Failed opening required ‘Doctrine/Common/ClassLoader.php’ (include_path=’;.;C:\php\pear’) i
        n C:\wamp\bin\php\zen_framework\bin\doctrine.php on line 30

        Call Stack:
        0.0008 241672 1. {main}() C:\wamp\bin\php\zen_framework\bin\doctrine.php:0

        /***************************************************************

        That’s the error I get. Thanks a lot!

  7. Just a word of thanks for taking the time to write this tutorial.
    Its not often (for me anyway) that I can follow a tutorial from the start to the end without problems, and be up and running so quickly!

  8. I try execute this:
    “Obinote@Obinote:/var/www/dczend/library/bin$ php doctrine.php ”

    Error
    PHP Warning: require_once(Doctrine/Common/ClassLoader.php): failed to open stream: No such file or directory in /var/www/dczend/library/bin/doctrine.php on line 21

    PHP Fatal error: require_once(): Failed opening required ‘Doctrine/Common/ClassLoader.php’ (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/dczend/library/bin/doctrine.php on line 21

    Obinote@Obinote:/var/www/dczend/library/bin$ php doctrine.php
    PHP Warning: require_once(Doctrine/Common/ClassLoader.php): failed to open stream: No such file or directory in /var/www/dczend/library/bin/doctrine.php on line 13

    PHP Fatal error: require_once(): Failed opening required ‘Doctrine/Common/ClassLoader.php’ (include_path=’:.:/usr/share/php:/usr/share/pear’) in /var/www/dczend/library/bin/doctrine.php on line 13

    And this is my folder

    dczend/
    —-application/
    —-docs/
    —-library/
    ——–bin/
    ——–doctrine/
    ——–zend/

    • Take a look into function _initDoctrine in Bootstrap and make sure the require_once of the classloader is correct:

      // include and register Doctrine’s class loader
      require_once(‘Doctrine/Common/ClassLoader.php’);
      $classLoader = new \Doctrine\Common\ClassLoader(
      ‘Doctrine’,
      APPLICATION_PATH . ‘/../library/’
      );
      $classLoader->register();

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>