Skip to content

Using Doctrine with Code Igniter

alanrew edited this page Jul 12, 2012 · 19 revisions

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 http://svn.phpdoctrine.org/branches/0.10/lib 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 http://svn.phpdoctrine.org/branches/0.10/lib

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
<?php
chdir(dirname(__FILE__));
include('doctrine.php');

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

<?php
require_once('config/database.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'  =>  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);
$cli->run($_SERVER['argv']);

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.

---
User:
  columns:
    username:
      type: string(255)
    password:
      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

<?php

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

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

<?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

---
User:
  jwage:
    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)
y
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-';
$user->setPassword('password');
$user->save();

$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;
}
Clone this wiki locally