Using Doctrine with Code Igniter

alanrew edited this page Jul 12, 2012 · 19 revisions
Clone this wiki locally

Learning about Doctrine

The best way to learn about Doctrine is to read about it in the manual. Here are some important links.

Doctrine 2 Documentation

Download Doctrine

First we must get the source of Doctrine from svn and place it in the system/database folder.

$ cd system/database
$ svn co doctrine
$ cd ..

// If you use svn in your project you can set Doctrine 
// as an external so you receive bug fixes automatically from svn
$ svn propedit svn:externals database

// In your favorite editor add the following line
// doctrine

Check Doctrine download page for the latest version

Setup Doctrine

Now we must setup the configuration for Doctrine and load it in system/application/config/database.php

$ vi application/config/database.php

The code below needs to be added under this line of code

$db['default']['cachedir'] = "";

Add this code

// Create dsn from the info above
$db['default']['dsn'] = $db['default']['dbdriver'] . 
                        '://' . $db['default']['username'] . 
                        ':' . $db['default']['password']. 
                        '@' . $db['default']['hostname'] . 
                        '/' . $db['default']['database'];

// Require Doctrine.php
require_once(realpath(dirname(__FILE__) . '/../..') . DIRECTORY_SEPARATOR . 'database/doctrine/Doctrine.php');

// Set the autoloader
spl_autoload_register(array('Doctrine', 'autoload'));

// Load the Doctrine connection
Doctrine_Manager::connection($db['default']['dsn'], $db['default']['database']);

// Load the models for the autoloader
Doctrine::loadModels(realpath(dirname(__FILE__) . '/..') . DIRECTORY_SEPARATOR . 'models');

Now we must make sure system/application/config/database.php is included in your front controller. Open your front controller in your favorite text editor.

$ cd ..
$ vi index.php

Change the last 2 lines of code of index.php with the following

require_once APPPATH.'config/database.php';
require_once BASEPATH.'codeigniter/CodeIgniter'.EXT;

Another Method to Bootstrap Doctrine

While the above listed technique is effective, it requires editing index.php, which I would like to avoid (to be sure upgrades are seamless I like to avoid all core CI files). CI provides a "hooks" mechanism that can be used in a much cleaner and easier fashion. This technique is described here

Setup Command Line Interface

Create the following file: system/application/doctrine and chmod the file so it can be executed. Place the code below in to the doctrine file.

$ vi system/application/doctrine

Place this code in system/application/doctrine

#!/usr/bin/env php

Now create the following file: system/application/doctrine.php. Place the code below in to the doctrine.php file.


// 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'  =>  dirname(__FILE__) . DIRECTORY_SEPARATOR . '/fixtures',
                'models_path'         =>  dirname(__FILE__) . DIRECTORY_SEPARATOR . '/models',
                'migrations_path'     =>  dirname(__FILE__) . DIRECTORY_SEPARATOR . '/migrations',
                'sql_path'            =>  dirname(__FILE__) . DIRECTORY_SEPARATOR . '/sql',
                'yaml_schema_path'    =>  dirname(__FILE__) . DIRECTORY_SEPARATOR . '/schema');

$cli = new Doctrine_Cli($config);

Now we must create all the directories for Doctrine to use

// Create directory for your yaml data fixtures files
$ mkdir system/application/fixtures

// Create directory for your migration classes
$ mkdir system/application/migrations

// Create directory for your yaml schema files
$ mkdir system/application/schema

// Create directory to generate your sql to create the database in
$ mkdir system/application/sql

Now you have a command line interface ready to go. If you execute the doctrine shell script with no argument you will get a list of available commands

$ cd system/application
$ ./doctrine 
Doctrine Command Line Interface

./doctrine build-all
./doctrine build-all-load
./doctrine build-all-reload
./doctrine compile
./doctrine create-db
./doctrine create-tables
./doctrine dql
./doctrine drop-db
./doctrine dump-data
./doctrine generate-migration
./doctrine generate-migrations-db
./doctrine generate-migrations-models
./doctrine generate-models-db
./doctrine generate-models-yaml
./doctrine generate-sql
./doctrine generate-yaml-db
./doctrine generate-yaml-models
./doctrine load-data
./doctrine load-dummy-data
./doctrine migrate
./doctrine rebuild-db

On Microsoft Windows, call the script via the PHP binary (because the script won't invoke it automatically:

> php.exe doctrine

Start Using Doctrine

It is simple to start using Doctrine now. First we must create a yaml schema file.

      type: string(255)
      type: string(255)

Now if you run the following command it will generate your models in system/application/models

$ ./doctrine generate-models-yaml
generate-models-yaml - Generated models successfully from YAML schema

Now check the file system/application/models/generated/BaseUser.php


 * This class has been auto-generated by the Doctrine ORM Framework
abstract class BaseUser extends Doctrine_Record
  public function setTableDefinition()
    $this->hasColumn('username', 'string', 255, array (
    $this->hasColumn('password', 'string', 255, array (

// Add custom methods to system/application/models/User.php


 * This class has been auto-generated by the Doctrine ORM Framework
class User extends BaseUser
  public function setPassword($password)
    $this->password = md5($password);

 * This class has been auto-generated by the Doctrine ORM Framework
class UserTable extends Doctrine_Table
  public function retrieveAll()
    $query = new Doctrine_Query();
    $query->from('User u');
    $query->orderby('u.username ASC');

    return $query->execute();

Now we can create some sample data to load in to our application(this step requires you have a valid database configured and ready to go. The build-all-reload task will drop and recreate the database, create tables, and load data fixtures

Create a file in system/application/fixtures/users.yml

$ vi fixtures/users.yml

Add the following yaml to the file

    username: jwage
    password: test

Now run the build-all-reload task to drop db, build models, recreate

$ ./doctrine build-all-reload
build-all-reload - Are you sure you wish to drop your databases? (y/n)
build-all-reload - Successfully dropped database named: "jwage_codeigniter"
build-all-reload - Generated models successfully from YAML schema
build-all-reload - Successfully created database named: "jwage_codeigniter"
build-all-reload - Created tables successfully
build-all-reload - Data was successfully loaded

Now we are ready to use Doctrine in our actual actions. Lets open our system/application/views/welcome_message.php and somewhere add the following code somewhere.

$user = new User();
$user->username = 'zYne-';

$userTable = Doctrine::getTable('User');
$user = $userTable->findOneByUsername('zYne-');

echo $user->username; // prints 'zYne-'

$users = $userTable->retrieveAll();

echo $users->count(); // echo '2''
foreach ($users as $user)
  echo $user->username;