Doctrine Tutorial
PHP May 28th, 2008When 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.
July 13th, 2008 at 9:31 pm
Hello,
Great job, but I think there is a mistake in config.php file.
Replace
HOST.DIRECTORY_SEPARATOR.DB
with
HOST.DIRECTORY_SEPARATOR.DATABASE
And then it runs perfectly.
Thank you.