1

Topic: ZC42 – Deep Integration between Zend and Doctrine 1.2

There's been a lot of talk online about finding the best approach for bringing Zend and Doctrine 1.x together. This video is my humble approach of combining some of the learning brought about over the last few weeks on Zendcasts, as well as suggestions from Doctrine developers. The goal of this video is to show how you leverage the existing resource loading tools in Zend to have a model structure that reflects Zend's best practices. This video builds on the last Doctrine video, but if you're familiar with both frameworks, you should be able to follow along. Enjoy!

Grab a copy of the project or browse the repository.

Also, a big thank you to ServerGrove for extending their support of Zendcasts for January. ServerGrove specializes in Zend Framework hosting and they've offered a 10% rebate on hosting with coupon code "zc". If you're looking for a host, be sure to check them out. They've also added an additional coupon for "Mini Hosting" plans, get $2 off by using code "zcmini".

2

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

Hi Jon,

You did it again! Another great zendcast. I've been looking for ways to implement ZF and Doctrine 1.2 for a while, and your very first tutorial on this topic gave me a lot of useful ideas.

I made myself a setup base on a merge from your "Writing Doctrine Unit Tests with Zend_Test" and  Eric Leclerc's zfdebugdoctrine project (http://github.com/danceric/zfdebugdoctrine).

Just want to share it with people who are interested. It can be found on github (http://github.com/marsbomber/zf-with-doctrine). Only major difference is that the doctrine command line script and any doctrine related stuff, like the schema yml file, the generated sql file, data fixture, etc, are placed out of the application directory. In a way I found it make my life a bit easier, when I deploy the application.

Can't wait for your next episode!

3

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

Hi marsbomber  ,
thanks for sharing your idea , its seems to be nice
I promise to take a detailed look of it ASAP
and i am look forward to hear form you

thanks again

4

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

i got

D:\Projects\ZF\doctrine\application\scripts>php.exe doctrine.php build-all-reload
build-all-reload - Are you sure you wish to drop your databases? (y/n)
y
build-all-reload - Successfully dropped database for connection named 'Doctrine'
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_Car in D:\Projects\ZF\doctrine\application\models\Car.php on line 16

after trying to generate my models etc

my Car.php class seems ok

class Model_Car extends Model_Base_Car {}

5

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

hey jon,

you where asking for ways of simplifying things...

there is good news which I posted here: http://www.zendcasts.com/forum/post/581/#p581

the bad news: It worked "the old way" but with the "deep integration" it doesn't work anymore.

so far I was not able to get it back to work but it shows some simplification potential. at least to schema files.

maybe someone else is able to figure it out.

6

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

detect relations is a great feature of Doctrine... I always forget to use it. Are you saying that this flag causes the model generation to fail when you're loading models with the Model_ prefix?

7

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

correct. when I use the detect_relation option I get this error at the end:

udos@ubuntu:/var/www/trailz.zf/application/scripts$ ./doctrine build-all-reload
PHP Warning:  Xdebug MUST be loaded as a Zend extension in Unknown on line 0
build-all-reload - Are you sure you wish to drop your databases? (y/n)
y
build-all-reload - Successfully dropped database for connection named 'doctrine'
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
Unknown method Model_User::setCar

Similar with running phpunit:

udos@ubuntu:/var/www/trailz.zf/tests$ phpunit
PHP Warning:  Xdebug MUST be loaded as a Zend extension in Unknown on line 0
build-all-reload - Successfully dropped database for connection named 'doctrine'
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
Unknown method Model_User::setCar
PHPUnit 3.4.9 by Sebastian Bergmann.

...F

Time: 2 seconds, Memory: 13.50Mb

There was 1 failure:

1) UserTest::testCanCreateUser
Failed asserting that <boolean:false> is true.

/var/www/trailz.zf/tests/application/models/UserTest.php:17

FAILURES!
Tests: 4, Assertions: 20, Failures: 1.

Generating code coverage report, this may take a moment.

Executing the scripts with your schema file (link) returns no errors.

It's probably related to the namespace, but so far I was not able to figure it out.

Note:
To make it easier to test this issue, I added this to application.ini:

; schema file (autodetect relations)
;doctrine.yaml_schema_path        = APPLICATION_PATH "/../doctrine/dev/schema-detrel.yml"
; schema file (relations specified by user)
doctrine.yaml_schema_path        = APPLICATION_PATH "/../doctrine/dev/schema.yml"

to easily switch between the schema files.

8

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

ok, found it. smile but I won't tell... it's embarassing... roll

Update:
Made up my mind. wink The problem was the following.

Remember my posted code from http://www.zendcasts.com/forum/post/581/#p581?

options:
  type: INNODB
  collate: utf8_general_ci
  charset: utf8
detect_relations: true

I indented detect_relations: true by 2 spaces because I thought it is an options property (which it's not):

options:
  type: INNODB
  collate: utf8_general_ci
  charset: utf8
  detect_relations: true

And the problems started...

Finally I removed the spaces in front of detect_relations: true and everything runs smoothly...

Lesson learned: Really be careful with spaces in YAML files! No kidding... smile

Update:
detect_relations is a parameter of the doctrine Global Schema Information.

9

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

I noticed another issue. I have to remove the following line from Bootstrap.php to make it work:

Doctrine_Core::loadModels($doctrineConfig['models_path']);

If I leave it, I get this when running

udos@ubuntu:/var/www/trailz.zf/application/scripts$ ./doctrine build-all-reload
PHP Warning:  Xdebug MUST be loaded as a Zend extension in Unknown on line 0
PHP Fatal error:  Class 'Model_Base_Car' not found in /var/www/trailz.zf/application/models/Car.php on line 14
PHP Stack trace:
PHP   1. {main}() /var/www/trailz.zf/application/scripts/doctrine:0
PHP   2. include() /var/www/trailz.zf/application/scripts/doctrine:4
PHP   3. Zend_Application_Bootstrap_BootstrapAbstract->bootstrap() /var/www/trailz.zf/application/scripts/doctrine.php:31
PHP   4. Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:579
PHP   5. Zend_Application_Bootstrap_BootstrapAbstract->_executeResource() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:622
PHP   6. Bootstrap->_initDoctrine() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:662
PHP   7. Doctrine_Core::loadModels() /var/www/trailz.zf/application/Bootstrap.php:32
PHP   8. require_once() /usr/local/lib/Doctrine/stable/1.2.1/lib/Doctrine/Core.php:664

Fatal error: Class 'Model_Base_Car' not found in /var/www/trailz.zf/application/models/Car.php on line 14

Call Stack:
    0.0008     317496   1. {main}() /var/www/trailz.zf/application/scripts/doctrine:0
    0.0013     323968   2. include('/var/www/trailz.zf/application/scripts/doctrine.php') /var/www/trailz.zf/application/scripts/doctrine:4
    0.0209     819440   3. Zend_Application_Bootstrap_BootstrapAbstract->bootstrap() /var/www/trailz.zf/application/scripts/doctrine.php:31
    0.0209     819440   4. Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:579
    0.0209     819440   5. Zend_Application_Bootstrap_BootstrapAbstract->_executeResource() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:622
    0.0212     820128   6. Bootstrap->_initDoctrine() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:662
    0.0283    1163804   7. Doctrine_Core::loadModels() /var/www/trailz.zf/application/Bootstrap.php:32
    0.0289    1194992   8. require_once('/var/www/trailz.zf/application/models/Car.php') /usr/local/lib/Doctrine/stable/1.2.1/lib/Doctrine/Core.php:664

Same thing for phpunit:

udos@ubuntu:/var/www/trailz.zf/tests$ phpunit
PHP Warning:  Xdebug MUST be loaded as a Zend extension in Unknown on line 0
PHP Fatal error:  Class 'Model_Base_Car' not found in /var/www/trailz.zf/application/models/Car.php on line 14
PHP Stack trace:
PHP   1. {main}() /usr/local/zend/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/local/zend/bin/phpunit:54
PHP   3. PHPUnit_TextUI_Command->run() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:146
PHP   4. PHPUnit_TextUI_Command->handleArguments() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:155
PHP   5. PHPUnit_Util_Fileloader::load() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:785
PHP   6. include_once() /usr/local/zend/share/pear/PHPUnit/Util/Fileloader.php:110
PHP   7. Zend_Application_Bootstrap_BootstrapAbstract->bootstrap() /var/www/trailz.zf/tests/application/bootstrap.php:41
PHP   8. Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:579
PHP   9. Zend_Application_Bootstrap_BootstrapAbstract->_executeResource() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:622
PHP  10. Bootstrap->_initDoctrine() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:662
PHP  11. Doctrine_Core::loadModels() /var/www/trailz.zf/application/Bootstrap.php:32
PHP  12. require_once() /usr/local/lib/Doctrine/stable/1.2.1/lib/Doctrine/Core.php:664

Fatal error: Class 'Model_Base_Car' not found in /var/www/trailz.zf/application/models/Car.php on line 14

Call Stack:
    0.0006     319792   1. {main}() /usr/local/zend/bin/phpunit:0
    0.0828    3215584   2. PHPUnit_TextUI_Command::main() /usr/local/zend/bin/phpunit:54
    0.0828    3215920   3. PHPUnit_TextUI_Command->run() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:146
    0.0828    3215920   4. PHPUnit_TextUI_Command->handleArguments() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:155
    0.0840    3219152   5. PHPUnit_Util_Fileloader::load() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:785
    0.0842    3226032   6. include_once('/var/www/trailz.zf/tests/application/bootstrap.php') /usr/local/zend/share/pear/PHPUnit/Util/Fileloader.php:110
    0.1167    4495016   7. Zend_Application_Bootstrap_BootstrapAbstract->bootstrap() /var/www/trailz.zf/tests/application/bootstrap.php:41
    0.1167    4495016   8. Zend_Application_Bootstrap_BootstrapAbstract->_bootstrap() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:579
    0.1167    4495016   9. Zend_Application_Bootstrap_BootstrapAbstract->_executeResource() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:622
    0.1170    4495704  10. Bootstrap->_initDoctrine() /usr/local/lib/ZF/stable/1.9.7/library/Zend/Application/Bootstrap/BootstrapAbstract.php:662
    0.1241    4839352  11. Doctrine_Core::loadModels() /var/www/trailz.zf/application/Bootstrap.php:32
    0.1258    4884880  12. require_once('/var/www/trailz.zf/application/models/Car.php') /usr/local/lib/Doctrine/stable/1.2.1/lib/Doctrine/Core.php:664

Did someone notice this also?

10

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

Hi Udo! ,
I think removing this line

PHP Code:
Doctrine_Core::loadModels($doctrineConfig['models_path']);

let the zend_autoloader load the models as a regular model and disable the functionality of the doctrine autoloader

Benjamin Eberlei aims to integrate Zend Framework and Doctrine 2 via Zend Tool.
Doctrine 2 CLI commands like Schema Tool should be integrated into the Zend
Tool Project context. This allows to setup the Doctrine 2 from withing
Zend Application within Zend Tool.
source :
http://framework.zend.com/wiki/display/ … in+Eberlei

until that we will face a lot of crazy error ...... just be patient
hope that help
Thanks

11

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

@marsbomber:

I also use this approach. It makes it easier for me to keep things separated from each other.

12

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

I can confirm the "A" problem, and it is likely that the reason is as Jochen already explained.

If something is kinda buggy from the beginning (or feels like that) I avoid it at any cost (remember "the broken window" rule?:).

I experimented a bit with nORKys settings, I found that is most stable solution for me. I moved models directory to /lib/MyCoolApp/Model and as I have module based project I can sorta mimic the logic with classes like: MyCoolApp_Model_Default_User, MyCoolApp_Model_Admin_User ect. It is a bit more typing (no problem if you use NetBeans or ect.) but there are no perfect solutions, and _initAppAutoload is not needed any more. Also then I can rely on my custom lightweight autoloader.

Pushing entire Dotctrine's autoloader just to load sfYmal is not a best Idea if you are concerned about performance, you can include those few files in bootstrap or add to your loader:

if (strpos($path, 'sfYaml') === 0) {
            include APPLICATION_ROOT . '/lib/Doctrine/Parser/sfYaml/' . $path . '.php';
return true;
        }

With that I have more robust solution, and no more strange problems with loading classes.

13

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

I can create an Instance of the Model (In Unit Test or Controller) but if i call a method of the Model i get and Exception saying "Model not found".
[...]
Edit: Found the Problem. I used "Model User" without the Underscore in my Model itself, in the Doctrine Method Call:

public function findAll() {
    Doctrine_Query::create()->
        from('Model User u')->execute();
}

But now it works with the Underscore attatched.

Last edited by as_lh (2010-04-30 15:14:11)

14

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

Could someone explain a little bit more on how and why Doctrine behaves like it does in the video. I have set up Doctrine like Jon has in the video but Doctrine still generates a generated folder with a Base folder in it. I'm trying to understand why it does that but can't figure it out.

I like my model classes named without the Model_ prefix:
doctrine.generate_models_options.classPrefix =

The generated folder now contains a Base folder with User.php and a Model_Base_User class name. Is it wise not to use the Model_ prefix? And why does Doctrine generate the generated folder with Base folder in it, and why are the Base class names like mentioned? I'm of course not asking for concrete answers here, any suggestion is welcome :-)

15

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

Hey dudes!

I got exactly the same error as jiewmeng up there...

D:\Projects\ZF\doctrine\application\scripts>php.exe doctrine.php build-all-reload
build-all-reload - Are you sure you wish to drop your databases? (y/n)
y
build-all-reload - Successfully dropped database for connection named 'Doctrine'
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_Car in D:\Projects\ZF\doctrine\application\models\Car.php on line 16

Anything to say about it? =/

Really thanks!

16

Re: ZC42 – Deep Integration between Zend and Doctrine 1.2

I have a problem with generate-migrations-diff.

doctrine.data_fixtures_path     = APPLICATION_DATA_PATH "/doctrine/fixtures"
doctrine.sql_path         = APPLICATION_DATA_PATH "/doctrine/sql"
doctrine.migrations_path     = APPLICATION_DATA_PATH "/doctrine/migrations"
doctrine.yaml_schema_path     = APPLICATION_DATA_PATH "/doctrine/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.baseClassPrefix      = "Base_"
doctrine.generate_models_options.baseClassesDirectory = 
doctrine.generate_models_options.classPrefixFiles     = false
doctrine.generate_models_options.classPrefix  = APPLICATION_NAMESPACE "_Model_"
doctrine.model_autoloading = 2

classPrefix = "Myapps_Model_"

Doctrine_Core::isValidModelClass($class)
$class equal User, but not Myapps_Model_User and Doctrine_Core::isValidModelClass($class) function return false.

How to make it work?


Zend Framework 1.10.4
Doctrine 1.2.2
PHP 5.3.2-1ubuntu4.2 with Suhosin-Patch (cli) (built: May 13 2010 20:03:45)

Sorry for my EN.

Last edited by xams (2010-05-23 14:12:59)