Skip to content

Using Doctrine with Code Igniter Conventions

Derek Jones edited this page Jul 5, 2012 · 30 revisions

1. Download Doctrine into the application/libraries folder.

cd /path/to/ci/install/
svn co http://svn.doctrine-project.org/tags/1.1.0-RC1 system/application/libraries/doctrine

This should download the entire doctrine project with tools, vendor and docs directories. This will allow you to run the command line out of the sandbox directory. If you're running off a different release or have a different directory structure at the very least you need the following Doctrine files:

system/application/libraries/doctrine/lib/Doctrine.php
system/application/libraries/doctrine/lib/Doctrine/

2. Add the config file

Create a new file in system/application/config/ named doctrine.php. This file should contain the following:

<?php

define('DOCTRINE_PATH', APPPATH . 'libraries' . DIRECTORY_SEPARATOR . 'doctrine' . DIRECTORY_SEPARATOR . 'lib');
define('DATA_FIXTURES_PATH', APPPATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'fixtures');
define('MODELS_PATH', APPPATH . 'models');
define('MIGRATIONS_PATH', APPPATH . 'migrations');
define('SQL_PATH', APPPATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'sql');
define('YAML_SCHEMA_PATH', APPPATH . DIRECTORY_SEPARATOR . 'schema');

require_once(DOCTRINE_PATH . DIRECTORY_SEPARATOR . 'Doctrine.php');

spl_autoload_register(array('Doctrine', 'autoload'));

Doctrine_Manager::connection('mysql://root:root@127.0.0.1/test');
Doctrine_Manager::getInstance()->setAttribute('model_loading', 'conservative');
Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL);

This is pieced together from the sandbox example and uses the default MAMP database settings. You'll probably need to change at least the MySQL settings but possibly the paths as well. Additionally if you plan on using the CLI then you'll want to replace out all instances of APPPATH with the full path.

3. Install the custom loader

In system/application/libraries/ you'll need to edit MY_Loader.php. If the file doesn't exist create it with the following shell:

class MY_Loader extends CI_Loader {
}

Then, once you have a MY_Loader.php add the doctrine() method to the MY_Loader class. After you're done it should resemble the following:

<?php

class MY_Loader extends CI_Loader {
    function doctrine($table=FALSE) {
        $ci =&get;_instance();
        
        if (!defined('DOCTRINE_PATH')) {
            require APPPATH.'config/doctrine.php';
        }
        
        if (!isset($this->doctrine_manager)) {
            $this->doctrine_manager = Doctrine_Manager::getInstance();
        }
        
        if ($table !== FALSE) {
            if (isset($ci->{$table})) {
                return $ci->{$table};
            }
            
            Doctrine::loadModels(MODELS_PATH);
            
            $ci->{$table} = Doctrine::getTable($table);
            return $ci->{$table};
        }
        
        return $this->doctrine_manager;
    }
}

4. Using Doctrine

Now that Doctrine is installed you'll have to set up your database tables and models manually. You can read the documentation and use the command line to automatically create things via YML. In effect you'll need something like the following in your models (you should be able to guess the MySQL table based on the hasColumn calls):

<?php

class Song extends Doctrine_Record {
    public function setTableDefinition() {
        $this->setTableName('library');
        $this->hasColumn('id', 'integer', 4, array('type' => 'integer', 'length' => 4, 'primary' => true, 'autoincrement' => true));
        $this->hasColumn('artist', 'string', 255, array('type' => 'string', 'length' => 255));
        $this->hasColumn('song', 'string', 255, array('type' => 'string', 'length' => 255));
    }
    
    public function setUp() {
        
    }
}

With that set up you can use Song in your controller something like this:

<?php

class Welcome extends Controller {
    function index() {
        $this->load->doctrine('song');
        $this->song->findAll();
        $song = $this->song->find(1);
        $song->artist;
        $this->song->find(1)->artist;
    }
    
}

5. Using Migrations

First you'll need to set up the command line interface of Doctrine by creating a file named doctrine in your system/application/ directory. In it place the following code. ALSO, make sure you replaced out all instances of APPPATH in your config/doctrine.php with the full application path as noted above.

#!/usr/bin/env php
<?php
chdir(dirname(__FILE__));

require_once('config/doctrine.php');

// Configure Doctrine Cli
// Normally these are arguments to the cli tasks but if they are set here the arguments will be auto-filled
$config = array('data_fixtures_path'  =>  DATA_FIXTURES_PATH,
                'models_path'         =>  MODELS_PATH,
                'migrations_path'     =>  MIGRATIONS_PATH,
                'sql_path'            =>  SQL_PATH,
                'yaml_schema_path'    =>  YAML_SCHEMA_PATH);

$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);

Then you'll need to create a database table to store the current migrated version, so run this query on your CI database:

CREATE TABLE `migration_version` (
  `version` int(11) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Finally, create the actual migration in a file named 001_create_songs.class.php inside system/application/migrations/ and add the following:

<?php

class CreateSongs extends Doctrine_Migration_Base {
    public function up() {
        $this->createTable('songs', array(
            'id' => array('type' => 'integer', 'length' => 4, 'primary' => true, 'autoincrement' => true),
            'artist' => array('type' => 'string', 'length' => 255),
            'song' => array('type' => 'string', 'length' => 255)
        ));
    }
    
    public function postUp() {
        Doctrine::loadModels(MODELS_PATH);
        Doctrine::getTable('song');
        
        $song = new Song();
        $song->artist = 'Starship';
        $song->song = 'We Built This City';
        $song->save();
    }
    
    public function preDown() {
        $song = Doctrine::getTable('songs')->findOneBySong('We Built This City');
        $song->delete();
    }
    
    public function down() {
        $this->dropTable('songs');
    }
}

Note that the documentation incorrectly specifies which class to extend, the above is correct do not follow the documentation as of 16 Jan 2009 ( http://trac.phpdoctrine.org/ticket/1805#comment:3)

Clone this wiki locally