Under development for more than two years, the first stable release of Doctrine 2 was made available this past December. This release provides users of PHP’s leading object-relational mapper with even more expansive capabilities for effectively managing data and relations using a convenient object-oriented interface.
I’ve been using Doctrine 2 in conjunction with the Zend Framework for several weeks now, and already wonder how I ever got along without it. In this article I’ll introduce you to Doctrine 2, helping you to get familiar with some of the key features at your disposal when using this incredibly powerful persistence solution.
By the way, Doctrine 2 takes advantage of several features available only to PHP 5.3, meaning you’ll need to upgrade to at least PHP 5.3.0 before continuing with this tutorial.
Installing the Doctrine 2 PHP ORM
Doctrine 2 can be installed in a variety of ways. The easiest in terms of experimenting with the solution is by cloning the project’s GitHub repository. Create a directory somewhere within your Web server’s document root, enter the directory, and execute the following command:
$ git clone git://github.com/doctrine/doctrine2.git
This clones only the ORM portion of the project. You also should retrieve the Common and DBAL projects, so enter the doctrine2
directory and execute the following commands:
$ git submodule init
$ git submodule update
Included in the release is a sample project, which we’ll use to get acquainted with Doctrine.
Experimenting with the Doctrine 2 Sandbox Project
A simple sample project called sandbox
is stored in the doctrine2/tools/sandbox
directory. This project is intended for you to familiarize yourself with key Doctrine concepts without having to spend a lot of time getting mired in configuration details. Navigate to the sandbox
directory and among other files you’ll find an executable named doctrine
. This is the Doctrine command-line console, which you can use to execute a variety of useful tasks. Display the command menu by executing the command from your terminal window:
$ ./doctrine
Doctrine Command Line Interface version 2.1.0-DEV
...
orm:schema-tool
:create
:drop
:update
...
Defining Persistent Classes in the Doctrine 2 PHP ORM
One of Doctrine’s great attributes is the flexibility it provides developers in terms of defining persistent classes. You can choose to manage your class declarations using XML, YAML, or DocBlock annotations. The sandbox project provides you with examples of all three approaches. You’ll find sample declarations in the xml
, yaml
, and Entities
directories, respectively. I prefer using the DocBlock annotations because of the added convenience of managing your domain class and persistence definitions together.
To see an example of a class that has been annotated, open the Entities/User.php
file:
<!--p
namespace Entities;
/** @Entity @Table(name="users") */
class User
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/** @Column(type="string", length=50) */
private $name;
/**
* @OneToOne(targetEntity="Address", inversedBy="user")
* @JoinColumn(name="address_id", referencedColumnName="id")
*/
private $address;
public function getId()
{
return $thi-->id;
}
public function getName()
{
return $this->name;
}
These annotations are prefixed with the @
symbol, and each plays a role in terms of determining how the class is persisted. The most important annotation is @Entity
, which tells Doctrine that this class should be persisted in the first place. The @Table
annotation defines the database table, which should be mapped to this class. Within the class you’ll find a series of datatype- and association-specific annotations, which collectively determine how the associated table should be defined and how it relates to other tables in the database. Once defined, these annotations can be used to generate the table schemas.
Generating the Table Schemas in the Doctrine 2 PHP ORM
With the persistence definitions in place, you can use the Doctrine console to generate the table schemas. The sandbox project uses the SQLite database by default, which is a file-based database solution. Generate the database and table schemas using the following command:
$ doctrine orm:schema-tool:create
ATTENTION: This operation should not be executed in a production environment.
Creating database schema…
Database schema created successfully!
View the directory contents and you’ll find a file named database.sqlite. Next, we’ll create a PHP script that connects to this SQLite database and uses Doctrine to interact with the tables via the persistent classes.
Talking to the Database Using the Doctrine 2 PHP ORM
The sandbox project’s index.php file contains all of the configuration-related code you’ll need to make the persistent classes and Doctrine library available to your website. Open this file and navigate to the bottom, where you’ll find the comment PUT YOUR TEST CODE BELOW
. Below this comment you’ll see that the two classes found in the Entities
directory are instantiated:
$user = new User;
$address = new Address;
Modify the code to look like this:
$user = new User;
$user->setName('Superman');
$address = new Address;
$address->setStreet('Fortress of Solitude');
$em->persist($address);
$user->setAddress($address);
$em->persist($user);
$em->flush();
Save the file and then execute it within the browser. Before doing so, make sure the database.sqlite
file and its parent directory are writable by your Web server. Congratulations, you’ve just saved your first persistent objects!
While it’s of course possible to retrieve the persistent data using the object-oriented interface (I’ll show you how to do this in a moment), I wanted to first show you how to use the Doctrine console to quickly query the database. Execute the following command:
$ ./doctrine dbal:run-sql "select * from users"
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "1"
["address_id"]=>
string(1) "1"
["name"]=>
string(8) "Superman"
}
}
Now let’s retrieve the data from the index.php file. Before modifying index.php though, execute the following command:
$ ./doctrine orm:generate-proxies
Proxies are used by Doctrine to facilitate the object-loading process. If you view the contents of the sandbox directory, you’ll see that a new directory named Proxies
has been created. Now modify index.php, replacing the previous snippet with the following:
$user = $em->getRepository('EntitiesUser')->findOneByName('Superman');
echo $user->getAddress()->getStreet();
Save index.php and reload the browser. You’ll see that Fortress of Solitude
is output!
About the Author
Jason Gilmore — Contributing Editor, PHP — is the founder of EasyPHPWebsites.com, and author of the popular book, “Easy PHP Websites with the Zend Framework”. Jason is a cofounder and speaker chair of CodeMash, a nonprofit organization tasked with hosting an annual namesake developer’s conference, and was a member of the 2008 MySQL Conference speaker selection board.