You are not logged in.
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".
Offline
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!
Offline
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
Offline
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 16after trying to generate my models etc
my Car.php class seems ok
class Model_Car extends Model_Base_Car {}
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.
Offline
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?
Offline
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::setCarSimilar 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.
Offline
ok, found it.
but I won't tell... it's embarassing... ![]()
Update:
Made up my mind.
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: trueI 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: trueAnd 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... ![]()
Update:
detect_relations is a parameter of the doctrine Global Schema Information.
Offline
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:664Same 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:664Did someone notice this also?
Offline
Hi Udo! ,
I think removing this line
[code=php]Doctrine_Core::loadModels($doctrineConfig['models_path']); [/code]
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
Offline
@marsbomber:
I also use this approach. It makes it easier for me to keep things separated from each other.
Offline
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.
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)
Offline
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 :-)
Offline
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 16Anything to say about it? =/
Really thanks!
Offline
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 = 2classPrefix = "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)
Offline
Hey Jon ,
Not fully implemented , but just thought this may work . I want to play more with doctrine and your way also .
But when watching the video I thought of taking the challenge to bring a solution for the module model generator
This will create models inside the module . We need to change prefix class path like the same
.
Hope this works
.
Offline
i try to integrate but i have some problems :S
first of all i use xml configuration file
i change your ini settings to xml and try to load it but when i realize it when i set classprefix doctrine cli creates automaticly model folder too i search all the web but didnt find anything about here my xml config
<autoloaderNamespaces>
<ZendX>ZendX</ZendX>
<Doctrine>Doctrine</Doctrine>
</autoloaderNamespaces>
<doctrine>
<dsn>mysql://USERNAME:PASSWORD@localhost/dbname</dsn>
<data_fixtures_path><zf:const zf:name="APPLICATION_PATH"/>/configs/doctrine/data/fixtures</data_fixtures_path>
<sql_path><zf:const zf:name="APPLICATION_PATH"/>/configs/doctrine/data/sql</sql_path>
<migrations_path><zf:const zf:name="APPLICATION_PATH"/>/configs/doctrine/migrations</migrations_path>
<models_path><zf:const zf:name="APPLICATION_PATH"/>/modules/default/models</models_path>
<yaml_schema_path><zf:const zf:name="APPLICATION_PATH"/>/configs/doctrine/schema.yml</yaml_schema_path>
<generate_models_options>
<pearStyle>true</pearStyle>
<generateTableClasses>false</generateTableClasses>
<generateBaseClasses>true</generateBaseClasses>
<baseClassPrefix>Base_</baseClassPrefix>
<baseClassesDirectory></baseClassesDirectory>
<classPrefixFiles>false</classPrefixFiles>
<classPrefix>Model_</classPrefix>
</generate_models_options>
</doctrine>
for cli
<doctrineCLI extends="production">
<model_loading>1</model_loading>
</doctrineCLI>and here my bootstrap init function
protected function _initDoctrine(){
$this->getApplication()->getAutoloader()->pushAutoloader(array('Doctrine','autoload'));
spl_autoload_register(array('Doctrine','modelsAutoload'));
$manager=Doctrine_Manager::getInstance();
$manager->setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE,true);
$manager->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE);
$manager->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, true);
$doctrineconfig=$this->getOption('doctrine');
Doctrine::loadModels($doctrineconfig['models_path']);
$conn=Doctrine_Manager::connection($doctrineconfig['dsn'],'doctrine');
$conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
return $conn;
}and last one doctrine.php in scripts folder
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/..'));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'doctrineCLI'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
)));
/** Zend_Application */
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.xml'
);
$application->getBootstrap()->bootstrap('doctrine');
$config= $application->getOption('doctrine');
$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);i use zf 1.10.8 and doctrine 1.2.3
i cant understand why it makes that
Last edited by tribesman (2010-09-10 11:26:11)
Offline
i found very interesting problem with application.ini and application.xml
i try to make similar with ini but when i change ini to xml in your project has errors like creating folder classprefix in models folder (models\model) didnt zend config read it like ini file ? on my server they disabled parse_ini for security reasons so i cant use ini format i must use xml ... but at this rate it becomes useless
may you look what can i do about xml configuration
Offline
i guess your xml is missing some nodes which Zend_Config is expecting (a root node and the nodes for different app environments).
an example xml which is working for me:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<production>
<autoloaderNamespaces>
<ZendX>ZendX_</ZendX>
<Doctrine>Doctrine_</Doctrine>
</autoloaderNamespaces>
[...]
</production>
<staging extends="production" />
<development extends="production" />
<testing extends="production" />
</configuration>hope that helps understanding your problem
Offline
at least i understand why it gives errors like that in ini format zend_config gets true to 1 false to null but in xml format it returns true or false and doctrine cant understand true or false values. i chance my xml file to doctrine config values trues are 1 and false's are blank. the error gone it works smootly
Offline
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
Offline
another strange error :S
i have tables, names started with aktivite... and it looks like doctrine doesnt like aktivite when i change model class names to kaktivite and related table class names problem gone :S
is it aktivite a special word in doctrine ?
Offline
there are a few 'reserved words' in mysql, normaly you could still use them using backticks (if im correct, doctrine made me lazy). but i doubt aktivite is one of them. Maybe if you post the error...
Offline
i had an
fatal error : class 'model_base_tablename' not found in 'model_tablename' on line 14
but when i change starting with aktivite to kaktivite problem goes away :S
Offline