ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Drop-in PHP Doctrine plugin

December 03, 2008 1:09pm

Subscribe [13]
  • #1 / Dec 03, 2008 1:09pm

    Nick Husher

    364 posts

    CI-Doctrine - built for Doctrine 1.0 (included in package)

    A colleague of mine recently turned me on to Doctrine, an Object-Relational Mapper for PHP5. There are plenty of great resources that explain exactly what using an ORM gets you, but for me it boils down to being able to transparently serialize objects into my database in a human-understandable way.

    The problem is that Doctrine didn’t really have CodeIgniter in mind when it was developed, so it can be a little difficult and confusing to install it in such a way as to be maintainable and comfortable to use for a CI developer. I read the Wiki article, which is a little dated (for version 0.1 rather that version 1.0), and requires hacking of core CodeIgniter files. I also found a helpful blog entry, which migrates any core hacking out into a hook, but it still required some configuration and couldn’t be selectively disabled on some pages (not every page needs that kind of page overhead). I want drop-in-and-go ease, and flexibility.

    So, I developed my own solution in the form of a CI plugin. It grabs information from the database.php configuration file, just like the hook, but is as simple as dropping it into your CI plugins directory and writing your schema file.

    The Readme file follows:

  • #2 / Dec 03, 2008 1:18pm

    Nick Husher

    364 posts

    Requirements:
    * A database supported by Doctrine
    * CodeIgniter (tested on v1.7)
    * PHP5
    * A working PDO library for your database of choice

    Installation:
    1. Drop this extracted directory into the plugins folder of your CI system directory.
    2. Create a directory within your application folder called “doctrine”
    2a. Create three directories within this doctrine directory named “fixtures”, “models”, and “schema”. Make sure the “models” directory has full write access (chmod 777)
    4. Configure your database connection as you would for CodeIgniter

    The schema directory will be where the Doctrine plugin will look for your yaml schema files as per the Doctrine manual. Models generated from those yaml files will be saved in the models directory (which is why the directory must have full write access). The fixtures directory contains any fixture data you may want to include: this data will be inserted into the database whenever the doctrine_populate_database method is called (more on that below).


    Configuration:
    The Doctrine plugin uses the database information as it exists in the database configuration file (/system/application/config/database.php). It should require zero configuration to install properly.

    Using Doctrine:
    To use Doctrine, you must first load the plugin into CodeIgniter. This can be done with “$this->load->plugin(‘doctrine’)”. From there, you gain access to the the full doctrine API, which should behave very much like a typical PHP project. In addition, there are some useful convenience functions added to the plugin file that make development (particularly developing schema and fixture information) more expedient.

    The primary ones are doctrine_install, doctrine_uninstall, and doctrine_reinstall. The install function will generate model files from the schema yaml, then instantiate the database using the CI configuration files, then insert the fixture data. Uninstall will do just the opposite: it will drop all the tables that were created by Doctrine and delete all the model files.

    You can control the order in which these things take place with a set of utility functions:

    doctrine_create_database: Creates the database from the doctrine model files it finds in the models directory. If there are no models in this directory, it will run doctrine_create_models before generating the database.

    doctrine_populate_database: Populates the database with data defined in your fixtures directory. Requires an installed database and generated models. It does not generate these things automatically.

    doctrine_destroy_database: Drops all tables created by Doctrine. Any tables that were not created or maintained by Doctrine will not be deleted.

    doctrine_create_models: Generates model files from the schema files found in the schema directory.

    doctrine_destroy_models: Deletes all files in the doctrine models directory.

    Troubleshooting:
    If you are unable to run the install function successfully, and are running Mac OS X, check if there is a .DS_Store file in your doctrine models directory. If so, delete it.

  • #3 / Dec 05, 2008 3:06pm

    Muser

    78 posts

    Thank you for your contribution!

    I started with doctrine 3 days ago and I’m a really newbie… :(
    I am using the implementation of the blog post that you say.

    Using this->load->plugin(‘doctrine’) PHP IDE like NetBeans or Eclipse PDT have autocompletion?

    Now I’m learning DQL language from the Doctrine documentation (the getting started and how to guides from Doctine project official page ara excellent). Doctrine documentation.

    Do you alternate doctrine querys and ci-db queries or Do you only are using doctrine?
    Libraries like CI_Session, or authentication libraries of the community are using ci-db database library… Are you recoding this libraries for use with Doctrine?

  • #4 / Dec 05, 2008 3:12pm

    Nick Husher

    364 posts

    You can use Active Record, raw SQL, and Doctrine interchangably. The goal was to integrate Doctrine as quickly as possible without damaging any core CI functionality or hobbling Doctrine unnecessarily.

    If you’re looking for something like CodeIgniter with a built-in ORM mapper, check out Kohana.

  • #5 / Feb 04, 2009 5:14am

    nice one, thanks Nick

  • #6 / Feb 16, 2009 5:48am

    acpbl

    3 posts

    Many thanks for this.

    Any idea on whether version 1.1 can be adapted in a similar fashion?

    In general what are your experiences with doctrine? Is it stable enough for a production environment? What about performance? I understand ofcourse there will be opportunities for optimising specific heavy queries with custom code. But for the standard things is there any significant impact on performance?

  • #7 / Mar 24, 2009 11:58am

    RedLeader

    33 posts

    First off, thanks for a great plugin.

    I currently have an issue with autoloading “conservative” and “aggressive” and I wanted to see if you could help me.

    I was reading the Doctrine 1.0 manual about Autoloading here:
    http://www.doctrine-project.org/documentation/manual/1_0/en/introduction-to-models#autoloading-models

    I want to lazy load my classes (conservative) because there is a slight performance boost because not all the classes get loaded everytime:

    [FILE: doctrine_pi.php]
    Doctrine_Manager::getInstance()->setAttribute('model_loading', Doctrine::MODEL_LOADING_CONSERVATIVE);

    However, when I try this I get an error in the browser.
    Here’s the error:

    Fatal error: Uncaught exception 'Doctrine_Table_Exception' with message 'Unknown method Doctrine_Table::getCreatedToday' in C:\Projects\www\projectx\system\plugins\doctrine\Doctrine\Table.php:2283 
    Stack trace: 
    #0 [internal function]: Doctrine_Table->__call('getCreatedToday', Array) 
    #1 C:\Projects\www\projectx\system\application\controllers\backend.php(288): Doctrine_Table->getCreatedToday() 
    #2 [internal function]: Backend->categories() 
    #3 C:\Projects\www\projectx\system\codeigniter\CodeIgniter.php(232): call_user_func_array(Array, Array) 
    #4 C:\Projects\www\projectx\www\index.php(116): require_once('C:\Projects\www…') 
    #5 {main} thrown in C:\Projects\www\projectx\system\plugins\doctrine\Doctrine\Table.php on line 2283

    It appears the function getCreatedToday() isn’t being recognised as a method of my CategoryTable class.  Strange because it is there in my class:

    <?php
    
    /**
     * This class has been auto-generated by the Doctrine ORM Framework
     */
    class CategoryTable extends Doctrine_Table
    {
    
        public function getCreatedToday()
        {
            return 'yo!';
        }
    }

    As you can see I have only built a test method called getCreatedToday() which doesn’t do much.  However, that’s not the point as the method itself isn’t being found.

    Note that this error doesn’t occur when I autoload aggressively (which is the default but I will state this line of code for clarity):

    Doctrine_Manager::getInstance()->setAttribute('model_loading', Doctrine::MODEL_LOADING_AGGRESSIVE);


    Can anyone please tell me why it’s not finding my method when “conservative” autoloading?

    Thanks for any help with this!

  • #8 / Mar 24, 2009 12:21pm

    can you post line 288 of your ‘backend’ controller? I’ve had no problems with conservative loading

  • #9 / Mar 24, 2009 12:29pm

    RedLeader

    33 posts

    can you post line 288 of your ‘backend’ controller? I’ve had no problems with conservative loading

    Sure, it’s just the call to the method:

    public function categories()
    {
        $categoryTable = Doctrine::getTable('Category');
        $categories = $categoryTable->getCreatedToday(); // line 288
        $this->load_template_view('backend/categories', $data);
    }
  • #10 / Mar 24, 2009 12:41pm

    most odd, these are my doctrine autoload settings, they’re probably out of date, I’ve been using these since Doctrine 1.0.1, but they’re still working with 1.1

    Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE);
    Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, TRUE);
  • #11 / Mar 24, 2009 12:51pm

    RedLeader

    33 posts

    most odd, these are my doctrine autoload settings, they’re probably out of date, I’ve been using these since Doctrine 1.0.1, but they’re still working with 1.1

    Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE);
    Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, TRUE);

    GSV you legend!  I added the 2nd line to autoload the table classes and it worked!  That bit clearly isn’t necessary when using AGGRESSIVE autoloading because it just loads every php file in the model directries!

    Thanks for posting that!

    Now onwards and upwards with my Doctrine learning curve…

    Oh, by the way, I’m still using Doctrine 1.0 because that’s what came with CI-Doctrine plugin.  Is it a simple matter of swapping out Doctrine 1.0 for 1.1 from the plugins directory?  Did it work straight away or cause any issues?

  • #12 / Mar 24, 2009 12:57pm

    yep, I’ve just been replacing the Doctrine core files each time a new version is released. just copy everything from the Doctrine ‘lib’ folder to the ‘doctrine’ folder in the plugin folder.

  • #13 / Mar 24, 2009 1:10pm

    RedLeader

    33 posts

    yep, I’ve just been replacing the Doctrine core files each time a new version is released. just copy everything from the Doctrine ‘lib’ folder to the ‘doctrine’ folder in the plugin folder.

    Great - I’ll try that out.

    I see this page mentions the differences between 1.0 and 1.1:
    http://www.doctrine-project.org/blog/doctrine-1-1-released

    It also details the SVN repo so I think I’ll add that as an SVN:External to my CI project 😊

  • #14 / Apr 08, 2009 6:29pm

    scor

    5 posts

    Great! 10xs!! I searched it for a long time 😊

  • #15 / Apr 26, 2009 2:21pm

    acpbl

    3 posts

    Hi all,

    great job this looks very promising.

    A couple of questions:

    1. Would the plugin work with multiple databases?
    2. What about name conflicts where the same table name is used in database A and database B. Is it possible to distinguish within the models definition?

    thanks in advance

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases