Introducing Doctrine 1.2 Integration

November 23rd, 2009

By popular demand, I’ve put together an introduction to Doctrine 1.2 integration with the Zend Framework. Doctrine is a fantastic ORM (object-relational mapping tool). If you’ve jumped from NHibernate or Hibernate and are itching to have a powerful tool for handling database relationships, Doctrine is probably your best bet. On the mailing lists, there’s a lot of talk about integrating Doctrine 2.0 into the 2.0 release of the Zend Framework. Regardless, this will help you get up to speed today. In next week’s video, I’ll show you how you can unit test those models in the Zend Framework.

Enjoy!

Edit: I spoke to Guilherme Blanco (one of the core developers behind Doctrine) and he kindly brought up some things I should bear in mind for my Doctrine / Zend set.
Doctrine’s autoloader configuration can be scaled back by doing PEAR style Model Loading (new to 1.2). Also, you can use Doctrine_Core instead of Doctrine since everything has been moved to Doctrine_Core in order to follow Zend-style namespacing.

lastly, you can register your own CLI tasks as part of Doctrine’s CLI script or just write them in the scripts/doctrine.php file. With this, you could have your newly-generated models placed in the necessary folders. I’ll be experimenting with this in the coming week.

Grab a copy of the project or browse the repository.

 

discuss video in the forum

35 Responses to “Introducing Doctrine 1.2 Integration”

  1. sNop says:

    Hi,

    Next video unit test. Why unit tests ? nobody use unit test ;) Can you show us how to use Doctrine on the real examples ?

    Thank you for great video, doctrine tutorials are very important for ZF users, because it will be supported be ZF dev team

  2. Mario says:

    Great screencast.

    I do not know the contents of the other but I’d suggest that you include in your models the PEAR/Zend namespace like Foo_User to see how did you solve the creation of the Base***.php files under the /models.

  3. nORKy says:

    Good job, but, I’m don’t register the Doctrine Loader :

    in initDoctrine :
    remove the pushAutoload()

    in application.ini :
    autoloaderNamespaces.0 = “Doctrine_

    in my included_path lib :
    ln -sfn /path/to/Doctrine/lib/Doctrine

    in your code : use Doctrine_Core, not Doctrine

  4. jon says:

    @sNop: I use unit tests as a simple and easy way to make sure that things are working without having to call my code from a Controller. While you might not be using them for every line of code (e.g. TDD), they’re still an easy way of showing how something works without dealing with the MVC design pattern.

    @nORKy: I’d rather not modify the Doctrine libraries since it can make maintaining / updating more complex (even if it’s just renaming a class). Besides, Doctrine 2 will resolve this issue!

  5. Hi,
    I i have one issue on generating cli.

    I want to use Model’s as Zend use them. So i configured doctrine config (in application ini)

    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 = false;
    doctrine.generate_models_options.generateBaseClasses = true;
    doctrine.generate_models_options.baseClassesDirectory = null
    doctrine.generate_models_options.classPrefixFiles = false

    doctrine.generate_models_options.classPrefix = “Model_”
    doctrine.generate_models_options.baseClassPrefix = “Db_”

    After generating cli i get error in cosole:

    y
    build-all-reload – SQLSTATE[HY000]: General error: 1008 Can’t drop database ‘zftest’; database doesn’t exist. Failing Query: “DROP DATABASE zftest”
    build-all-reload – Generated models successfully from YAML schema
    build-all-reload – Successfully created database for connection named ‘doctrine’
    build-all-reload – Created tables successfully
    PHP Fatal error: Cannot redeclare class Model_User in /Users/vaidas/Server/testas.dom/application/models/User.php on line 16

    Fatal error: Cannot redeclare class Model_User in /Users/vaidas/Server/testas.dom/application/models/User.php on line 16

    Any ideas how to fix? It’s seems it trying to load same file 2 times. One time by zend fr, second doctrine loader

  6. After some time studing i found problem which name is NameSpace.

    On generatating Zf NameSpace must have name, on normal way i dont use them.

    protected function _initAppAutoload()
    {
    $sNameSpace = “”;
    if (defined(‘APP_NAMESPACE_HACK’) && APP_NAMESPACE_HACK == 1) {
    $sNameSpace = “App”;
    }
    $autoloader = new Zend_Application_Module_Autoloader(array(
    ‘namespace’ => $sNameSpace,
    ‘basePath’ => dirname(__FILE__),
    ));
    return $autoloader;
    }

  7. dave says:

    think you for this project
    but it miss an important thing : an exemple to use the doctrine object ! :)
    a controller and script to read User would be great

    I tried to just load your User Doctrine class
    and I have always the error ‘Class ‘User’ not found’
    (but if I try to create a table in doctrine it’s ok)

    I tested with
    $user = Doctrine_Core::getTable(‘User’);
    $nameTable=$objUser->getTable();
    (or $objUser = new User();)

    did you test using User in your project ? :)
    please tell a little example on it and all will be perfect

    think in advance

  8. dave says:

    and by the way test units for Doctrine integrated in Zend would be great :)

    but before a little example to using Data Doctrines object like your User (search and why not edit) in a controller/view would be very cool

  9. jon says:

    hey Dave… the model should be generated in the build-all-reload script. Are you sure the object is properly created?

  10. Harald says:

    Hi. Very interesting video. I’m quite new to zend framework and completely new to doctrine, but i will to learn how to use it.

    I downloaded the project and tried to run it but I’m getting this error. I’m not shure if its related to xampp, zend or doctrine. Can anyone help?

    Error message:
    “Warning: include(Doctrine\Locator\Injectable.php) [function.include]: failed to open stream: No such file or directory in D:\dev\xampp\php\PEAR\Zend\Loader.php on line 83

    Warning: include() [function.include]: Failed opening ‘Doctrine\Locator\Injectable.php’ for inclusion (include_path=’D:\dev\xampp\htdocs\doctrineintro\application/../library;D:\dev\xampp\htdocs\doctrineintro\library;.;D:\dev\xampp\php\PEAR’) in D:\dev\xampp\php\PEAR\Zend\Loader.php on line 83

    Fatal error: Class ‘Doctrine_Locator_Injectable’ not found in D:\dev\xampp\htdocs\doctrineintro\library\Doctrine\Configurable.php on line 35″

  11. dave says:

    think for your response

    what I did :
    I download your project, installed it on my server and changed the database connexion in .ini

    because all is in your project I used it directly
    but to be certain I regenerated it with script, which worked to create class and tables but change nothing :

    when I test a doctrine creation connexion it’s ok : $conn->export->createTable(‘test’, array(‘name’ => array(‘type’ => ’string’))); $conn->execute(‘INSERT INTO test (name) VALUES (?)’, array(‘ohoui’));

    but when I test using object User, with is in your project, it tells me Couldn’t find class User :
    $objUser = Doctrine_Core::getTable(‘User’);

    so can you tell an example how you select the table User in your project ?

    the problem for me is not to generate, but to using the class in zend.
    please note the Zend loading and Doctrine core loading are ok. the class User is here but Doctrine/Zend don’t load it

    think in advance

  12. dave says:

    and I’m impatient to see your test units with Zend/Doctrine ! ;)
    (if I can load the User table in your project… I will be a big fan of you !)

  13. dave says:

    well I just looked your unit test… and see you just used
    $u = new User();

    but for me it’s always “Class ‘User’ not found”… (but please note Eclipse found it and the class and BaseUser are here)
    So it seems I miss something in autoload… which is strange because I use your download project :(

  14. jon says:

    hey dave, did you include the zend framework from my code example? I don’t post my code samples with a copy of the framework due to the file size.

  15. dave says:

    Hello Jon, yes and I test it in your controller/view index
    Zend is ok, Doctrine is ok (which I tested with creating table in index) but loading Data Doctrine class don’t :(

  16. dave says:

    to be certain I redownload all your project, add zend, change nothing, and of course always the problem when I put in
    views/scripts/index/index.phtml :
    $u=new User();
    > Class ‘User’ not found

    It seems to me it miss something to direct autoload generated doctrine class in your project view ?

  17. dave says:

    (but please note the User class is here, and Doctrine and Zend class too because in your project)

    did you try to direct create the User object ?

  18. dave says:

    well it can find User class if I add to boostrap include path to models and generated directory and set zend autoloader.
    but then it doesn’t find the UserTable :

    $rootDir = dirname(dirname(__FILE__));
    define(‘ROOT_DIR’, $rootDir);
    set_include_path(get_include_path()
    .PATH_SEPARATOR.ROOT_DIR.’/application/models/’
    .PATH_SEPARATOR.ROOT_DIR.’/application/models/generated’
    );

    require_once ‘Zend/Loader/Autoloader.php’;
    $loader = Zend_Loader_Autoloader::getInstance();
    $loader->setFallbackAutoloader(true);

    >
    Warning: Zend_Loader::include(UserTable.php) [zend-loader.include]: failed to open stream

    well at least it is not any more an error :)
    but it seems the autoload in your project don’t run to direct use User object in view, or did I miss something ?

  19. Andry says:

    Dave I’ve got the same problem with you, this is how I solved it:

    under application.ini add these lines
    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.generateAccessors = false

    And on Bootstrap.php under _initDoctrine() I added this code:
    Doctrine_Core::setModelsDirectory($doctrineConfig['models_path']);

    just after $doctrineConfig = $this->getOption(‘doctrine’);

    And it should work

  20. dave says:

    think Andry !
    I have tried another tutorial doctr/zend which work not bad but not perfect, grr ! I hope soon there will be the zend/doctrine component !

    I’ll try your tip, I’ll said if it work ! :)

  21. [...] Lebensold hat einen Zend Cast über die Integration von Doctrine 1.2 [...]

  22. dave says:

    think Andry !

    well now it find User, but not BaseUser :
    Error: Class ‘BaseUser’ not found in (…)\User.php

    so it found User, but only with
    $users = Doctrine_Core::getTable(‘User’)->find();

    if I use $user = new User(); it don’t find it

    so I suppos autoload don’t really work here
    :(

  23. jnunez says:

    Hi Dave,

    Not sure if you are still having issues with the item above but if you copied and paste the code provided by Andry check the double quotes around Base_ make sure they are not the “smart quotes”.

  24. dave says:

    hello Jnunez !

    well I began a new project with “Doctrine Relations and Data Fixtures”, which talked about my problem autoloading and it fixed it
    think’s ! :)

  25. daniel says:

    where is the video???

  26. jon says:

    I believe its there! When in doubt just download from the RSS feed.

  27. [...] Introducing Doctrine 1.2 Integration [...]

  28. lexterv says:

    Hello, thanks for this very helpful screencast, i have been able to follow it pretty easily. tryed almost every doctrine command and they all worked. But when i try load the fixtures i get an error saying couldn’t find class user…

  29. jon says:

    Hi lexterv,

    using build-all-reload should load the data fixtures as well.

  30. MiST says:

    For those of you, working with Windows and XAMPP. The Doctrine shell script looks a bit like this.

    /application/scripts/doctrine.bat

    @ECHO off

    SET PHP_BIN=../../../../php/php.exe
    SET DOCTRINE_SCRIPT=doctrine.php
    “%PHP_BIN%” -d safe_mode=Off -f “%DOCTRINE_SCRIPT%” — %*

    Assuming that your project is in the htdocs folder.

    With this, you can run doctrine build-all-reload in the console.

  31. mysticav says:

    Mist, I’m using Zend Server CE on Windows, and for me it was enough to just remove the shebang line (first line). I ended up with this:

    # Start Script

    <?php
    chdir(dirname(__FILE__));
    include('doctrine.php');

    # End Script

    Everything works perfect. This is a great tutorial, indeed.

  32. E:S says:

    @mysticav – actually under Windows is should be enough to enter “php doctrine.php” in the command line ;) I’m using Zend Server CE as well.

    Kind regards,
    E:S

  33. Küpper says:

    Hey there!
    I’m having problems with this:

    “spl_autoload_register(array(‘Doctrine’, ‘modelsAutoload’));”

    Rises a big stack of error!!

    Fatal error: Uncaught exception ‘LogicException’ with message ‘Passed array does not specify an existing static method (class ‘Doctrine’ not found)’ in C:\xampp\htdocs\doctrine_zend\application\Bootstrap.php:11 Stack trace: #0 C:\xampp\htdocs\doctrine_zend\application\Bootstrap.php(11): spl_autoload_register(Array) #1 C:\xampp\php\PEAR\Zend\Application\Bootstrap\BootstrapAbstract.php(662): Bootstrap->_initDoctrine() #2 C:\xampp\php\PEAR\Zend\Application\Bootstrap\BootstrapAbstract.php(615): Zend_Application_Bootstrap_BootstrapAbstract->_executeResource(‘doctrine’) #3 C:\xampp\php\PEAR\Zend\Application\Bootstrap\BootstrapAbstract.php(579): Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap(NULL) #4 C:\xampp\php\PEAR\Zend\Application.php(347): Zend_Application_Bootstrap_BootstrapAbstract->bootstrap(NULL) #5 C:\xampp\htdocs\doctrine_zend\public\index.php(25): Zend_Application->bootstrap() #6 {main} thrown in C:\xampp\htdocs\doctrine_zend\application\Bootstrap.php on line 11

    Is there any tips to solve this?

    Thanks!

  34. Küpper says:

    Aaaa, sorry dudes, my problem is soved, I missed the namespace config on application.ini

    So sorry, and thanks again!

  35. Vincent says:

    Following the tutorial I got my CLI working but all the webrequests keep returning errors:

    exception ‘Zend_Application_Bootstrap_Exception’ with message ‘Unable to resolve plugin “doctrine”; no corresponding plugin with that name’ in /home/tastedev/lib/Zend/Application/Bootstrap/BootstrapAbstract.php:330
    Stack trace:
    #0 /home/tastedev/lib/Zend/Application/Bootstrap/BootstrapAbstract.php(379): Zend_Application_Bootstrap_BootstrapAbstract->getPluginResource(‘doctrine’)
    #1 /home/tastedev/lib/Zend/Application/Bootstrap/BootstrapAbstract.php(391): Zend_Application_Bootstrap_BootstrapAbstract->getPluginResources()
    #2 /home/tastedev/lib/Zend/Application/Bootstrap/BootstrapAbstract.php(621): Zend_Application_Bootstrap_BootstrapAbstract->getPluginResourceNames()
    #3 /home/tastedev/lib/Zend/Application/Bootstrap/BootstrapAbstract.php(582): Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap(NULL)
    #4 /home/tastedev/lib/Zend/Application.php(355): Zend_Application_Bootstrap_BootstrapAbstract->bootstrap(NULL)
    #5 /home/tastedev/www/index.php(13): Zend_Application->bootstrap()
    #6 {main}

    Anyone got an idea what I did wrong?

Leave a Reply

Desktop RSS feed iPhone + iPod