When writing an application that has poetential to grow it is important to use Object Relational Mapping(ORM) to access data in your database. Doctrine for PHP is an ORM which generates models for your tables, giving you access to methods to update/delete/insert/find records in your database. It also supports the relationships between objects through the table relations.

Getting Started

Firstly you should download the Doctrine sandbox zip. This is a pre-configured environment good to go. It currently is configured for SQLite so usually the first thing you would want to do is change it to work with MySQL instead.

To enable support for MySQL change your /config.php file to:

<?php 
define('SANDBOX_PATH', dirname(__FILE__));
define('DOCTRINE_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR.'lib');
define('DATA_FIXTURES_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'fixtures');
define('MODELS_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'models');
define('MIGRATIONS_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'migrations');
define('SQL_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'sql');
define('YAML_SCHEMA_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'schema');
 
define('HOST', 'localhost');
define('DATABASE', 'database');
define('USERNAME', 'username');
define('PASSWORD', 'password');
 
require_once(DOCTRINE_PATH . DIRECTORY_SEPARATOR . 'Doctrine.php');
 
spl_autoload_register(array('Doctrine', 'autoload'));
 
Doctrine_Manager::connection('mysql://'.USERNAME.':'.PASSWORD.'@'.HOST.DIRECTORY_SEPARATOR.DB);
Doctrine_Manager::getInstance()->setAttribute('model_loading', 'conservative');
?>

Command Line Interface

The command line interface (CLI) is a task list available from command line. It is used to run the most common tasks such as build-all-reload, build-all, drop-db, generate-sql (more).

For most of the changes that I do with Doctrine I just simply use the command build-all-reload, and this command will:

  • Drop the tables of the database
  • Insert the tables from the schema.yml into the database
  • Insert the test data fixtures from the /data/fixtures/ directory
  • Generate the models for each of the tables into /models/ directory
./doctrine build-all-reload

Defining Your Schema

In order for Doctrine to generate the models and relationships between objects it needs to look at a schema. I have played around with generating the models on an existing database but I had some troubles, so I recommend that you write your schema out and let Doctrine create your models and database from it.

The schema files are in YAML format and are stored in /schema/ (configured in the config.php file).

You should create a schema.yml file:

User:
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(4)
    username: string(255)
    password: string(255)
  relations:
    Groups:
      class: Group
      refClass: UserGroup
      foreignAlias: Users
 
Group:
  tableName: groups
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(4)
    name: string(255)
 
UserGroup:
  columns:
    user_id: integer(4)
    group_id: integer(4)
  relations:
    User:
      onDelete: CASCADE
    Group:
      onDelete: CASCADE

Test Fixtures

In your /data/fixtures/ directory you can put all the fixtures you need. Fixtures are in YAML format. You can create a test.yml file in your /data/fixtures/ directory:

User:
  zyne:
    username: zYne-
    password: changeme
    Groups: [founder, lead, documentation]
  jwage:
    username: jwage
    password: changeme
    Groups: [lead, documentation]
 
Group:
  founder:
    name: Founder
  lead:
    name: Lead
  documentation:
    name: Documentation

Using Data

<?php
	from('User u, u.Groups g');
	$users = $query->execute();
 
	echo '<pre>';
	print_r($users->toArray(true));
?>

Pagination

Pagination is important for any set of data and Doctrine provides the classes needed to paginate any kind of query you may have, and customise the results. To create a simple pager you can use this code on our User object:

<?php
from( 'User u' )
        ->leftJoin( 'u.Group g' )
        ->orderby( 'u.username ASC' ),
    $currentPage, // Current page of request
    $resultsPerPage // (Optional) Number of results per page. Default is 25
);
 
$results = $pager->execute();
 
foreach($results as $user)
{
  echo $user->username;
}
?>

You may user the methods inside your Doctrine_Pager ($pager) object to create your own page numbering at the bottom. Some methods are:

  • $pager->haveToPaginate();
  • $pager->getLastPage();
  • $pager->getNumResults();
  • $pager->getPreviousPage();
  • more…

Extending the Models

If you look inside the /models/ directory you should notice the files that Doctine generated from your schema.yml file. You may use and extend on the files in that directory without them being affected by re-running the CLI command build-all-reload, which will only overwrite the files in /models/generated/.

I hope this article helps you get started using Doctrine. Please leave a comment if you have any questions.