Welcome Guest, Not a member yet? Register   Sign In
WebTigers: Working with Doctrine ORM, Part 1
#1

[eluser]webtigers[/eluser]
Having just begun working with Doctrine within CI, I thought I'd post some of my code and limited experience to date. Doctrine, in a word, ROCKS!, but like any other piece of complex software, this ORM has its idiosyncrasies. Hopefully, my experiences will help you avoid some of the gotchas I ran into.

INSTALLING DOCTRINE AS A CI PLUG-IN

There are quite a few helpful blogs discussing how to use Doctrine with CI. My preference is to use Doctrine as a CI Plug-in, which seems to make the most sense within the MVC framework.

The Doctrine site discusses integrating Doctrine with CI but has you hacking the CI system code to do it. DON'T DO THIS! Doctrine works just fine as a CI plug-in without your having to hack it into the system code.

First, download the Doctrine source files from the Doctrine website at http://www.doctrine-project.org/projects/orm/download. (Don't bother with their SVN if you're not using SVN, most of us are using GitHub or BitBucket anyway these days.)

Unpack the Doctrine-1.2.x folder into your CI /application/plugins folder. Rename it simply "Doctrine". (This allows you to upgrade the plug-in later without changing path code deeper within your application.)

You should now have within your plugins folder a /Doctrine/lib/Doctrine/ ... directory tree that contains all of the Doctrine files.

Now we're going to create the Doctrine CI plug-in file which will act as our Doctrine "bootstrap" file and initialization code. This file lives in the root of the /plugins directory and will be named appropriately, doctrine_pi.php

To give credit where credit is due, some of this I borrowed from Burak at PHP and Stuff

Code:
<?php

// File Name & Location: ./application/plugins/doctrine_pi.php


// Load Doctrine library
require_once APPPATH.'plugins/doctrine/lib/Doctrine.php';


// This will allow Doctrine to load Model classes automatically
spl_autoload_register( array('Doctrine', 'autoload') );
spl_autoload_register( array('Doctrine_Core', 'modelsAutoload') );


// Load database configuration from CodeIgniter
require_once APPPATH.'config/database.php';


// We load our database connections into Doctrine_Manager.
// This loop allows us to use multiple connections later on.
foreach ($db as $connection_name => $db_values)
{
    // first we must convert to dsn format
    $dsn = $db[$connection_name]['dbdriver'] .
        '://' . $db[$connection_name]['username'] .
        ':' . $db[$connection_name]['password'].
        '@' . $db[$connection_name]['hostname'] .
        '/' . $db[$connection_name]['database'];

    Doctrine_Manager::connection($dsn,$connection_name);
}


// Enforce connection character set. This is very important if you are
// using MySQL and InnoDB tables!
Doctrine_Manager::connection()->setCharset('utf8');
Doctrine_Manager::connection()->setCollate('utf8_general_ci');


// (OPTIONAL) CONFIGURATION BELOW

// Create a Doctrine reference
$DM = Doctrine_Manager::getInstance();


// This will allow us to use "mutators"
$DM->setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);


// This sets all table columns to notnull and unsigned (for ints) by default
$DM->setAttribute(Doctrine::ATTR_DEFAULT_COLUMN_OPTIONS,
    array('notnull' => true, 'unsigned' => true));


// set the default primary key. Frankly, this might be useful, but it has its
// problems if you're not using INT(4) primary keys, which I don't use. Comment
// this out if your primary keys are UUID's which we'll discuss later on.

//$DM->setAttribute(Doctrine::ATTR_DEFAULT_IDENTIFIER_OPTIONS,
//    array('name' => 'id', 'alias' => null, 'type' => 'integer', 'length' => 4, 'options' => array(
//        'fixed' => true, 'unsigned' => true, 'primary' => true, 'notnull' => true, 'autoincrement' => true)));


// Tells Doctrine to validate all data. This seemed like a good idea out of the gate
// but it caused problems with the auto insertion of UUID's. Don't use it if you don't
// really need it.
// $DM->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);


// This allows us create tables with constraints
$DM->setAttribute(Doctrine_Core::ATTR_EXPORT, Doctrine_Core::EXPORT_ALL);


// Load only the models we need and none that we don't
$DM->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_CONSERVATIVE);


// Allows autoloading of custom table classes
$DM->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);


// CodeIgniter's Model class needs to be loaded since we'll be running Doctrine from
// within the model layer. Don't build Doctrine calls from within your controllers --
// that's really bad and it breaks the security and data isolation of the MVC!
require_once BASEPATH.'libraries/Model.php';


// telling Doctrine where our models are located
Doctrine::loadModels(APPPATH.'models');


/* End of file doctrine_pi.php */
/* Location: ./application/plugins/doctrine_pi.php */

Finally, within in your concrete controller you'll need to add this code:

Code:
class Some_Controller extends Controller
{
    function __construct()
    {
        parent::Controller();

        // autoload plugins
        $this->load->plugin('doctrine');
    }
    
    ...
}

Now Doctrine is fully available for us to use within our models. Very cool.

In my next post, I'll show how to create some basic tables using Doctine's YAML config code, use UUID's and build a related table -- and ALL without writing a single line of SQL! Good stuff ... stay tuned.
#2

[eluser]Unknown[/eluser]
Didn't work for me

Fatal error: Class 'User' not found in E:\server\xampp\htdocs\CI\system\application\controllers\hello.php

Could you please let me know what should it be for doctrine 1.2.3
Here User was the class..
#3

[eluser]developer10[/eluser]
When using Doctrine as CI plugin, do we really have to write the DQL queries directly in our controllers or there is a way for writing them in doctrine models and them call those models from controllers (just like we would normally do if not using Doctrine)?
#4

[eluser]webtigers[/eluser]
[quote author="cold_fusion" date="1288399879"]When using Doctrine as CI plugin, do we really have to write the DQL queries directly in our controllers or there is a way for writing them in doctrine models and them call those models from controllers (just like we would normally do if not using Doctrine)?[/quote]

Simple object method calls are fine. But you really should not have complex DQL queries in your controllers. Doing so breaks the MVC separation rules. Place complex queries within the model as a function and then call that function with whatever appropriate params from the controller once the object is instantiated. Much cleaner this way also. Smile
#5

[eluser]webtigers[/eluser]
[quote author="ajax_bnr" date="1285618560"]Didn't work for me

Fatal error: Class 'User' not found in E:\server\xampp\htdocs\CI\system\application\controllers\hello.php

Could you please let me know what should it be for doctrine 1.2.3
Here User was the class..[/quote]

You'll just need to debug your code. Doctrine works very well and I've been using it successfully to create tables, populate and pull data. It's quite cool.
#6

[eluser]developer10[/eluser]
[quote author="WebTigers" date="1288486255"][quote author="cold_fusion" date="1288399879"]When using Doctrine as CI plugin, do we really have to write the DQL queries directly in our controllers or there is a way for writing them in doctrine models and them call those models from controllers (just like we would normally do if not using Doctrine)?[/quote]

Simple object method calls are fine. But you really should not have complex DQL queries in your controllers. Doing so breaks the MVC separation rules. Place complex queries within the model as a function and then call that function with whatever appropriate params from the controller once the object is instantiated. Much cleaner this way also. Smile[/quote]

is this a proper way to call a method from Doctrine Model:
Code:
$var = Doctrine::getTable('Someclass');
$data['categories'] = $var->methodName($param1, $param2);

I have something like this but it doesnt work!
#7

[eluser]webtigers[/eluser]
[quote author="cold_fusion" date="1288489839"][quote author="WebTigers" date="1288486255"][quote author="cold_fusion" date="1288399879"]When using Doctrine as CI plugin, do we really have to write the DQL queries directly in our controllers or there is a way for writing them in doctrine models and them call those models from controllers (just like we would normally do if not using Doctrine)?[/quote]

Simple object method calls are fine. But you really should not have complex DQL queries in your controllers. Doing so breaks the MVC separation rules. Place complex queries within the model as a function and then call that function with whatever appropriate params from the controller once the object is instantiated. Much cleaner this way also. Smile[/quote]

is this a proper way to call a method from Doctrine Model:
Code:
$var = Doctrine::getTable('Someclass');
$data['categories'] = $var->methodName($param1, $param2);

I have something like this but it doesnt work![/quote]

Check out http://www.doctrine-project.org/document...-to-models

and

http://www.doctrine-project.org/projects...-models/en




Theme © iAndrew 2016 - Forum software by © MyBB