CodeIgniter and Doctrine
The most widely sited source for how to bootstrap Doctrine with CodeIgniter is available on the CI Wiki. While this approach is effective, I found it a bit intrusive into the CI code. I didn’t like the idea of having to edit index.php, and I didn’t like that the database.php, which should really only contain configuration code, was hijacked to actually do the bootstrapping. So I looked into it a bit, and I think there is a cleaner (if not easier) way.
The goal when bootstrapping Doctrine is to load up your database connection and point to your models folder. Thats pretty much it. Once you do that, all your models autoload, so you don’t need to do things like $this->load->mode('User'). Instead you can simply use Doctrine’s tools such as new User() or Doctrine::getTable('User').
So here is the process:
1. Install a “hook” that will bootstrap Doctrine. Edit application/config/hooks.php and add the following:
$hook['pre_controller'][] = array( 'function' => 'bootstrap_doctrine', 'filename' => 'doctrine.php', 'filepath' => 'hooks' );
2. Copy the following to application/hooks/doctrine.php
// YOU MUST EDIT THIS TO BE THE PATH TO YOUR DOCTRINE LIBRARY // I put mine in a 'libs' folder at the same level as the // CI application folder, but it can be anywhere. require_once APPPATH . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'libs' . DIRECTORY_SEPARATOR . 'Doctrine' . DIRECTORY_SEPARATOR . 'Doctrine.php'; function bootstrap_doctrine() { @include APPPATH . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'database' . EXT; // Set the autoloader spl_autoload_register(array('Doctrine', 'autoload')); //optional, you can set this to whatever you want, or not set it at all Doctrine_Manager::getInstance()->setAttribute('model_loading', 'aggressive'); // Load the Doctrine connection // (Notice the use of $active_group here, to make it easy to swap out // you connection based on you database.php configs) if (!isset($db[$active_group]['dsn'])) { //try to create the dsn, if it has not been manually set //in your config. I personally would opt to set my //dsn manually, but it works either way $db[$active_group]['dsn'] = $db[$active_group]['dbdriver'] . '://' . $db[$active_group]['username'] . ':' . $db[$active_group]['password']. '@' . $db[$active_group]['hostname'] . '/' . $db[$active_group]['database']; } Doctrine_Manager::connection($db[$active_group]['dsn']); // Load the models for the autoloader // This assumes all of your models will exist in you // application/models folder Doctrine::loadModels(APPPATH . DIRECTORY_SEPARATOR . 'models'); }
3. Done. Doctrine and its models are now available in the usual Doctrine way in all of your controllers.
Let me know if you have questions!
Hello!
Great article!
I made exactly that, but I get the message:
Fatal error: Class ‘Model’ not found in /var/www/project2/system/application/models/my_model.php on line 2
do you know how can I resolve?
thanks
Comment by Ricardo — October 9, 2008 @ 1:19 pm
So, you have a my_model.php file that extends Model? That does not appear to be a typical Doctrine model class. First, you do not need the MY_ prefix for classes in your models folder. Secondly, if you are making a Doctrine model, then you need to extend Doctrine_Record in your class. So if you did want a class called my_model, you could do:
class MyModel extends Doctrine_Rectord {
function setTableDefinition() {
//set up your model fields
}
}
Then, assuming you inserted the bootstrap technique above, you could access your MyModel class in your controller using:
$model = new MyModel();
or
Doctrine::getTable(’MyModel)->findAll()
You get the idea…
Comment by maulin — October 10, 2008 @ 12:48 am
Hey,
I’m trying to integrate Doctrine into a new CI app I’m working on. I’m getting the error…
Uncaught exception ‘Doctrine_Table_Exception’ with message ‘Class “CI_Base” must be a child class of Doctrine_Record’ in C:\Users\Tom\Desktop\xampplite\htdocs\gkci\lib\doctrine\Doctrine\Table.php:288
Any idea on how to fix this?
Thanks for the help!
Comment by Tom — October 20, 2008 @ 5:23 pm
Hey, I solved my problem.
Some of my doctrine models were named the same as my CI controllers.
I named my Code Ignitor controller Account, which there was also a doctrine model named Account, so these two class names were conflicting
Solved this issue by simply changing the CI controller to Account(s) with an s at the end.
Hope this helps anyone that got stuck on the same issue.
Tom
Comment by Tom — October 20, 2008 @ 7:28 pm
I think this is a great improvement from the Wiki method as I also hate to hack the core
I was thinking nonetheless, by applying this method you’re always Autoloading Doctrine, which might not be what desired in some cases.
Wouldn’t i make sense to use a plugin instead of a hook ?
In that way you can call
[code]
$this->load->plugin(”doctrine”);
[/code]
whenever you really need it
Comment by barbazul — November 8, 2008 @ 11:48 pm
I’m glad I have moved on from CodeIgniter and Doctrine to Kohana, which is like CI in a lot of ways but is PHP5 and comes with great ORM…
Check it:
http://docs.kohanaphp.com/libraries/orm
Comment by john — November 20, 2008 @ 2:38 am
Hello and thanks for an informative post.
How would you setup the cl interface, based on that method?
Comment by dxrsm — December 5, 2008 @ 12:53 am
[...] March 28 2009 Zaki saved Stop Caching Old Files - A PHP Function and CodeIgniter and Doctrine on Delicious. 02:00 am - No [...]
Pingback by links for 2009-03-27 — Mior Muhammad Zaki: PHP & JavaScript Programmer — March 27, 2009 @ 7:26 pm
hi there,
Great article. Well I am trying to use Doctrine as you said. But am getting an errror:
Fatal error: Class ‘abc’ not found in F:\wamp\www\system\application\controllers\lab.php on line 11
i am clueless. I am using 1.7.2 version of ci. I have also populated the database field in config
Comment by Codemaster Snake — October 7, 2009 @ 9:16 pm
btw here is the code of my model abc.php under modles flder
<?php
class abc extends Doctrine_Record {
function setTableDefinition() {
//set up your model fields
}
}
Comment by Codemaster Snake — October 7, 2009 @ 9:18 pm
Fatal error: Uncaught exception ‘Doctrine_Connection_Mysql_Exception’ with message ‘SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘johndoe’ for key 2′ in C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection.php:1082 Stack trace: #0 C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection\Statement.php(269): Doctrine_Connection->rethrowException(Object(PDOException), Object(Doctrine_Connection_Statement)) #1 C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection.php(1042): Doctrine_Connection_Statement->execute(Array) #2 C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection.php(687): Doctrine_Connection->exec(’INSERT INTO use…’, Array) #3 C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection\UnitOfWork.php(631): Doctrine_Connection->insert(Object(Doctrine_Table), Array) #4 C:\AppServ\www\ci_doctrine_day1\system\ap in C:\AppServ\www\ci_doctrine_day1\system\application\plugins\doctrine\lib\Doctrine\Connection.php on line 1082
plz tell me what does it mean.
Comment by hamza — December 15, 2009 @ 5:38 pm
It works and much better than editing index.php and database.php file. Thanks for sharing..
Comment by endless beginning — May 11, 2010 @ 10:54 am
i wonder with this technique, how do i autogenerated class models using cli.
this code is cleaner but the code in wiki have capability to autogenerated doctrine class model.
Comment by netfusion — May 22, 2010 @ 2:59 pm