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”.

Good job.
This is some tips :
you don’t need to set ‘aggressive’ for the cli and ‘conservative’ for the ‘http’ request.
You don’t need to use Doctrine.php
You don’t need to copy/link vendor.
how ?
In _initDoctrine :
remove
Doctrine,autoload and modelsAutoload
add (need only for the class ‘sfYmal’ )
$this->getApplication()->getAutoloader()->pushAutoloader(array(‘Doctrine_Core’, ‘autoload’));
add
$manager->setAttribute(Doctrine_Core::ATTR_MODEL_CLASS_PREFIX, ‘Model_’);
update
$manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_PEAR);
update all ref Doctrine to Doctrine_Core
That’all.
Why did you create the _initAppAutoload method?
this ensures that we get the proper Model_ loading behaviour since models are considered a “resource” in Zend (like the application/forms/ folder contains Form_ objects.) Not sure if this is a hold-over or if ZF is moving more in this direction though…
Isn’t the right way for setting up doctrine implementing application resource, instead having _initDoctrine in your bootstrap?
@umpirsky: The application resource is a good move, however it adds yet another level of indirection, which when you’re trying to get the two frameworks to work properly initially, can simply add confusion. I’ve seen implementations of the application resource, however if you’re not going to be running the resource in more than one place and its a database-driven website, what’s the point?
I watched all the casts from this awesome site, and just wanted to thank you for what you’re doing!!!
In the past I have used
Doctrine_Core::loadModels($doctrineConfig['models_path']);
in my _initDoctine method instead of creating the _initAppAutoload method. I guess that’s where my confusion came from. Any real difference behind the scenes between the two approaches?
Great screencast! Keep them coming.
Hm… everything worked fine (except of the things you already mentioned) until I changed from CONSERVATIVE to AGGRESSIVE when using CLI. Now when I have deleted all Model and Base/Model classes and run build-all-reload it works, DB is created, tables are creates, fixtures are filled and the Application runs without erros afterwards. BUT if I do changes to the schema and want to run build-all-reload again (now Models and auto-generated Base Model files exist) I get a fatal error:
Fatal error: Class ‘Model_Base_Album’ not found in C:\…\Album.php on line 14
So the generated Base Models are not found. Can anyone help me with this?
Unbelievable… I renamed “Album” to “Music” and it worked? WTF???
@ahue
I think the reason could be that aggressive loading just recurses through your models directory and loads everything it finds. Since “Album” is alphabetically before “Base”, the Base_ classes just aren’t loaded yet when it gets to Album.php. When it loads Music.php, it has already recursed into the Base directory and loaded the base classes.
WTF???
Hehe, the “a” Problem. Every Model starting with an a causes that problem. Give it a try, strange voodoo!
Hi, after I’ve set the model loading to aggressive creating the tables failed silently. I figured out that there is an issue with class_exists php internal function at line 782 in doctrine_core class’s isValidModelClass function. Somehow it throws a silent error that preventing to function properly I replaced it with “in_array($class, get_declared_classes())” and the tables have been created successfully. That’s probably my compiled MAMP 1.8.2 or ZF’s (1.9.5) autoload mechanism related bug or something other.
If somebody encountered the same problem maybe that helps.
r. Sandor
same problem.. I need at least three models beginning at ‘a’, so it’s quite fed-upping every time delete this three models and recovering all methods after rebuild models or db..
any solution Jon?
)
that’s a pretty strange bug! I’d try and hold out for Doctrine 2 if I could… The Doctrine team is pretty responsive as well, I would shoot them an email or check the bug tracker.
Hi Jon, thanks for your casts, they are very interesting. But after the “deep integration” of doctrine my phpunit test fails.
“create-tables – Created tables successfully
SQLSTATE[42S02]: Base table or view not found: 1146 Table ‘apptest.car’ doesn’t exist”
My database “apptest” ist created but there is no table in it.
greeting
tobias
Tobias, try putting
doctrine.model_autoloading = 1
in your “testing” section of application.ini if it’s not there already.
Hello, nice tutorial. I ran into some troubles, the Cli just couldn’t run when the models were already generated. It just kept throwing exceptions that “Model_Base_MyTable” wasn’t found. To solve it i added the following code in the cli “scripts/doctrine.php”: $application->getBootstrap()->bootstrap(‘autoload’);
Just before the bootstrap of ‘doctrine’.
Thanks, Regards.
I’m having a BIG issue with phpunit and doctrine (deep integration).
Baically, the problem happens when I run phpunit and the code coverage report takes
place.
It starts by looking the classes in models directory.
When it finds the first class, let say “User”
and because “User” class is defined as
“Model_User extends Model_Base_User”
it throws an error:
“Generating code coverage report, this may take a moment.
Fatal error: Class ‘Model_Base_User’ not found in [mypath]\application\models\User.php on line 14″
Jon, Can you please let us know what changes we should make in “tests/boostrap.php” so we can follow this video without break our phpunit testing capabilities ?
A very dirty solution could be adding a “require_once(Base/User.php)” in the Model File. Unacceptable solution, indeed.
Hi everyone!
Just a question a little bit offtopic:
Is there any way to pass the doctrine_collection object to a partial (partialLoop)? It seems that it implements iterator, but I can’t use the objects (car and user) into the “partial” code. Should I use the foreach statement and forget the partialLoop?
Thanks a lot
Great work here, this page has really helped me get going with Zend/Doctrine integration, thanks.
I think the problem with using Doctrine_Core::MODEL_LOADING_PEAR with CLI mode originates in scripts/doctrine.php where you do:
$application->getBootstrap()->bootstrap(‘doctrine’);
This calls _initDoctrine() but never _initAppAutoload(). The best way to correct the situation is to add this line to _initDoctrine():
$this->bootstrap(‘appAutoload’);
Very good job, but what about doctrine extensions? How to autoload them?
@Funk Face
Your comment was a life saver!
I would do one thing differently though. Since all _init methods get run on each request, instead of adding that line to the _initDoctrine method, I just took the contents of my _initAppAutoload method and stuck them at the beginning of _initDoctrine. This way the _initAppAutoload code only gets run once inside a normal application (not cli).
@jon
I find myself continually returning to your site as a reference. Thanks for all the hard work!
Nice Vid!
I am also working on a Doctrine 1.2 / ZF integration right now.
I have used Doctrine for the past 2 years now (before 1.0). You don’t have to write your own findAll function, doctrine has one fore you (http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/en#magic-finders)
in your case u can simply write:
Doctrine_Core::getTable(‘Model_Car’)->findAll();
which will also work if you do not have generated the Table class.
most of the time i use this only for building the views, cause i need to add some filtering and ordering to the queries
Hi there!
Great casts here. So far they’ve been really helpful. I’ve got a question though.
I’ve integrated Doctrine & Zend and I changed the class prefix for the Doctrine models to Model_ as suggested in this cast.
I’m wondering if it is somehow possible to configure Doctrine to use that standard class prefix, so I can use the ‘old’ class names in my queries without the prefix (i.e: User instead of Model_User)?
I can relate to the $user = new Model_User() as a classname, but somehow I find the Doctrine::getTable(‘Model_User’)->findAll(); statement a bit odd.
I’d prefer the Doctrine::getTable(‘User’)->findAll(); statement with Doctrine configured to add the class prefix Model_ automatically.
Does anyone know if this is possible? Any help would be appreciated…
Great video.
I’m having tons of trouble getting this working. I have latest Zend (1.10.x) and Doctrine (1.2) and I can’t get it working. NOTE: I’m on Windows.
I keep getting:
LogicException: Passed array does not specify an existing static method in C:\verisign\trusted\application\Bootstrap.php on line 15
and Warning: include_once() [function.include]: Failed opening ‘Doctrine.php’ for inclusion
I have under /library
/library/Zend
/library/Doctrine
Any suggestions?
I think I fixed this. I just needed to change many of the references in bootstrap from Doctrine to Doctrine_Core.
Hi!
Great casts! Thank you for them!
Can you make Doctrine 2.0 integration video?
TIPS :
If you have problem with UTF-8 encoding inside your database. Especially for French or other characters like (é, à ù etc. ..)
Just before returning your connection in your in your bootstrap file, specify the encoding
_initDoctrine function {
…
$conn->setCharset(‘UTF8′);
return $conn;
}
…of course i should write it like this :
protected function _initDoctrine()
{
…
$conn->setCharset(‘UTF8′);
return $conn;
}
Great job!!
Thanks from Brazil!
doctrine version 1.2.3
zf version 1.10.8
i have some error about class not found. i try many code but i didnt realize why it generate that error. i use xml format configuration and i copy this tutorials code, it works smootly.same code as yours and same version of doctrine both (last version 1.2.3). when i try to load at your schema.yml it works great but when i try to put my schema.yml(this files generated from db via doctrinecli) doctrine didnt create tables, it gives successfull message. when i generate models from db or yaml it doesnt matter doctrine cli starts giving fatal error class not found
I can use models created via db in zend and getting results but i cant use relational save or get. Same yaml file generated from db i can create db but cant create new tables.
if anything wrong in yaml file why it gives error generate models via db :S
i have unique multiplecolumns 2 or 3 tables did this make that error?
if i wrote yaml file i think about some wrong writing but it generates from db :S i am really confused
@nORKy
thank you for this life-saving comment! It seems to be a very nice solution!
Hi,
I follow this tutorial with doctrine version 1.2.3 and zf version 1.10.8.
When I try the build-all-reload, the models classes aren’t generated, but when I use build-all, the classes are generated.
It’s not a big problem, but I can’t figure it out why models classes can’t be generated.
Thanks for your help
@samy
Doctrine 1.2.3
ZF 1.10
I had the same confusing behavior and always did two steps:
# ./doctrine generate-models yaml
#./doctrine BuildAllReload
Now I got rid of these and made changes of library/Doctrine/Task/BuildAllRebuild.php
Maybe there is a reason why the Doctrine Developers left the Task of Models Generating within BuildAllRebuild Task.
However, I (re?)added it:
diff –git a/library/Doctrine/Task/BuildAllReload.php b/library/Doctrine/Task/BuildAllReload.php
index f06475c..ccd95cc 100644
— a/library/Doctrine/Task/BuildAllReload.php
+++ b/library/Doctrine/Task/BuildAllReload.php
@@ -39,16 +39,18 @@ class Doctrine_Task_BuildAllReload extends Doctrine_Task
public function __construct($dispatcher = null)
{
parent::__construct($dispatcher);
-
+ $this->models = new Doctrine_Task_GenerateModelsYaml($this->dispatcher);
$this->rebuildDb = new Doctrine_Task_RebuildDb($this->dispatcher);
$this->loadData = new Doctrine_Task_LoadData($this->dispatcher);
- $this->requiredArguments = array_merge($this->requiredArguments, $this->rebuildDb->requiredArguments, $this->loadData->requiredArguments);
- $this->optionalArguments = array_merge($this->optionalArguments, $this->rebuildDb->optionalArguments, $this->loadData->optionalArguments);
+ $this->requiredArguments = array_merge($this->requiredArguments, $this->models->requiredArguments, $this->rebuildDb->requiredArguments, $this->loadData->requiredArguments);
+ $this->optionalArguments = array_merge($this->optionalArguments, $this->models->optionalArguments, $this->rebuildDb->optionalArguments, $this->loadData->optionalArguments);
}
public function execute()
- {
+ { $this->models->setArguments($this->getArguments());
+ $this->models->execute();
+
$this->rebuildDb->setArguments($this->getArguments());
$this->rebuildDb->execute();
Hi,
I have strange problem. When I create new instance of class, setup some parameters, save it and after that load from db, it returns only numbers. For example:
$u = new Model_User();
$u->name = “user1″;
$u->save();
$u2 = Doctrine_Query::create()->from(‘Model_User u’)->where(‘u.id =?’,1)->execute();
echo $u2->name; //it prints something like number “3″
when I call another parametr:
echo $u2->password; //it prints “4″
echo $u2->email; //prints “5″
but if I call var_dump($u2->toArray());
it prints array of arrays with right values. So I would like to ask if anybody know what´s happening? Maybe it´s some misconfiguration, but I´m lost withnout error message:) And when I call var_dump(..) immediately after echo $u2->name, the array of arrays contains twice much values with second half null values. Thx for any kind of advice.
Tom
Really great work,
Best tutorial I have ever seen…
Could you add something about using dojo or extjs with the zend framework.
so I can get the idea about creating desktop like application on web which consist good coding standard and UI like desktop .
Thanks in advance mate.
Hi,
thanks A LOT for your very attractive screencast.
I ‘ve just a few questions :
1°) as Norky seems to indicate, it is possible to load Doctrine models through the Zend autoloader mechanism. Why, then should we need to “update” Doctrine_Core::ATTR_MODEL_LOADING attribute.
2°) AFAIC we can use the “short” form of models name in the yaml schema file. EG., in Doctrine internals there seems to be a mean to map the “short” form name to the “classPrefix” declared in application.ini file. Why, then should we have to use the long form of models name in the DQL declaration or in the fixture file ?
thx again for you screencast.
@Frederic
Hi,
thats a good question. Did you fiddle with this and have some more findings about this issue?
I also find the Model_Foobar thing a little annoying.
CU Sven
@Jon
Although, zendcasts.com tutorials are freely available and made up by big efforts of you,
the last weeks I got a little disappointed because of no new content.
I hope you’re alive and kicking?! Although (or because
) the tutorials aren’t perfect, sometimes I feel I’m sitting with a buddy in a php hacking session to fight together against issues, haha.
Some warm words before christmas.
CU Sven
I have been having difficulty unit testing with phpunit and doctrine on model classes that extend other model classes. I have found on the doctrine website (http://www.doctrine-project.org/documen … -to-models) that “Doctrine can not satisfy any inheritance and if your models extend another model, it cannot include them in the correct order so it is up to you to make sure all dependencies are satisfied in each class.”
This makes unit testing problematic for me. I have many models that extend. Putting require statements in each one seems a bit cumbersome. Does anyone have any solutions or resources to check out. I have watched the ZC42 – Deep Integration between Zend and Doctrine 1.2 but this is not addressed as far as I can tell.
@Jeffery I think a mapped superclass would be perfect for what you’re trying to do. I would suggest looking at Doctrine 2 integration.
@jon
After looking over Doctrine 2, it is not clear to me that the implementation is the same. Do you have any recommendations?
@Jeffrey
Doctrine 2 is in many ways a rewrite of Doctrine. It’s borrowing a lot of concepts from Hibernate, including a real query parser and the ability to write POPOs (Plain Old PHP Objects). Both of these features were lacking in Doctrine 1 and necessitated a lot of re-engineering and a focus on the Unit of Work pattern and an entity manager for handling transactions. They’ve also created two projects: DBAL (database abstraction layer) and ORM (object relational mapper) in order to further separate persistence abstraction from relational mapping.
Hope that helps,
-
Jon
If anyone is having troubles getting doctrine to work with MAMP and receiving errors similar to: “PDO Connection Error: SQLSTATE[HY000] [2002] No such file or directory”. You should append the ‘–unix_socket’ option to your doctrine dsn string in application.ini as follows:
doctrine.dsn = “mysql://user:password@localhost/test;unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock”