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.
-
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)
-
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; } } -
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"
-
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); -
Now you can execute Doctrine’s from CLI and test that the correct version appears and that is functional:
php doctrine.php
-
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
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.
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)
Pingback: Aus den Blogs: Zend Framework und Doctrine, Capistrano, CRUD, NetBeans, Magento, WordPress, Restful - Zend Framework Magazin
Pingback: Zend Framework and Doctrine 2 integration. « Codeperl's Knowledge Sharing System
Would you mind if I put this up on github with some additional changes for cache drivers in production vs development. Excellent write up btw.
Of course, feel free to use this code. Thanks!
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.
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 .
You have a require_once where it does not belong, but without seeing any code I can’t tell you much more…
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
Make sure you are in the directory where the file is!
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!
Lovely tutorial – Nice to see one not using Bisna library!
Worked first time; thanks very much
Nice to see it helps!
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!
Glad it helped!
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();