Using doctrine2 for ORM in PHP

After having some small steps into PHP Data Objects, I went a step further. Instead of using basic SQL-commands via PDO-Layer, with doctrine2 comes a great framework which extends the basic database-layer of PDO with an own strong database-abstraction-layer (DBAL) and an object-relation-mapper (ORM). While PDO is comparable to JDBC, doctrine2 is strongle oriented at Java’s Hibernate-framework.

In this scenario I’m using following configuration:

  • USB-Webserver v. 8.5 (incl. Apache HTTP 2.2.21, PHP 5.3.9 and MySQL 5.5)
  • doctrine2
  • And my example from the pdo-post

First, we have to set PHP_HOME to $USB_WEBSERVER_HOME\php. Then we have to download doctrine2 via composer (the PHP-equivalent of Maven). So first, we create and goto PHP_COMPOSER_HOME somewhere on your machine. Then save http://getcomposer.org/download as $PHP_COMPOSER_HOME/download-composer.php and finally execute „php download-composer.php“. The composer.phar will be automatically downloaded to $PHP_COMPOSER_HOME.

Now the basics are set and we need a composer.json (let’s say the php-pom.xml 🙂 )
create $PHP_COMPOSER_HOME/composer.json:

 {  
     "require": {  
         "doctrine/orm": "*"  
     }  
 } 

Install doctrine via

php composer.phar install --verbose

this should be the result:

D:\phpcomposer>php composer.phar install --verbose
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing doctrine/common (2.3.0)
    Downloading: 100%
    Extracting archive

  - Installing symfony/console (v2.3.3)
    Downloading: 100%
    Extracting archive

  - Installing doctrine/dbal (2.3.4)
    Downloading: 100%
    Extracting archive

  - Installing doctrine/orm (2.3.4)
    Downloading: 100%
    Extracting archive

symfony/console suggests installing symfony/event-dispatcher ()
doctrine/orm suggests installing symfony/yaml (If you want to use YAML Metadata Mapping Driver)
Writing lock file
Generating autoload files

Now you find all the doctrine-stuff in $PHP_COMPOSER_HOME/vendor-directory. You just have to copy the whole vendor-dir to your webspace and make sure, you have at least php 5.3 enabled, because doctrine is using the cool namespaces-feature of php, that ships first with 5.3.

The setup:

first the db-setup:

DROP TABLE IF EXISTS `dojos`;
CREATE TABLE IF NOT EXISTS `dojos` (
  `id` int(2) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
 
INSERT INTO `dojos` (`id`, `name`) VALUES
(1, 'Dojo A'),
(2, 'Dojo B'),
(3, 'Dojo C'),
(4, 'Dojo D');
 
DROP TABLE IF EXISTS `starters`;
CREATE TABLE IF NOT EXISTS `starters` (
  `id` int(3) NOT NULL auto_increment,
  `name` varchar(20) NOT NULL,
  `dojo` int(2) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `FK_starters` (`dojo`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
 
INSERT INTO `starters` (`id`, `name`, `dojo`) VALUES
(1, 'Burmeister', 1),
(2, 'Klingenberger', 2),
(3, 'Lee', 2),
(4, 'Norris', 2),
(5, 'Miyagi', 3),
(6, 'Mishima', 4),
(7, 'Kang', 1),
(8, 'Tsung', 2),
(9, 'Dux', 1);
 
--
-- Constraints for table `starters`
--
ALTER TABLE `starters`
  ADD CONSTRAINT `FK_starters` FOREIGN KEY (`dojo`) REFERENCES `dojos` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Now the files in usb-webserver-root:

  • entities/Dojo.php
  • entities/Starter.php
  • vendor/(here you’ll put the composer-, doctrine- and symfony-files)
  • bootstrap.php
  • index.php
<?php
/**
 * @Entity @Table(name="starters")
 **/
class Starter{
    /** @Id @Column(type="integer") @GeneratedValue **/
    protected $id;
    /** @Column(type="string") **/
    protected $name;
	/** @Column (type="integer") **/
	protected $dojo;
	
    public function getId(){
        return $this->id;
    }

    public function getName(){
        return $this->name;
    }

    public function setName($name){
        $this->name = $name;
    }

    public function getDojo(){
        return $this->dojo;
    }

    public function setDojo($dojo){
        $this->dojo = $dojo;
    }
}
<?php
/**
 * @Entity @Table(name="dojos")
 **/
class Dojo
{
    /** @Id @Column(type="integer") @GeneratedValue **/
    protected $id;
    /** @Column(type="string") **/
    protected $name;

    public function getId(){
        return $this->id;
    }

    public function getName(){
        return $this->name;
    }

    public function setName($name){
        $this->name = $name;
    }
}
<?php

require_once 'vendor/autoload.php';

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;

$paths = array("/entities");
$isDevMode = false;

// the connection configuration
$dbParams = array(
    'driver'   => 'pdo_mysql',
    'user'     => 'root',
    'password' => 'usbw',
    'dbname'   => 'registration_db',
	'host'	   => 'localhost',
	'port'	   => '3307',
);

$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$entityManager = EntityManager::create($dbParams, $config);

<?php

require_once "bootstrap.php";
require_once "entities/Dojo.php";
require_once "entities/Starter.php";

$dojoRepo = $entityManager->getRepository('Dojo');
$starterRepo = $entityManager->getRepository('Starter');

$dojos = $dojoRepo->findAll();
$starters = $starterRepo->findAll();

echo "<table border='1'>";
echo "<tr><th>id</th><th>name</th><th>dojo-id</th><th>dojo-name (referenced from dojos)</th></tr>";
foreach ($starters as $starter) {
	$id = $starter->getId();
	$name = $starter->getName();
	$dojoId = $starter->getDojo();
	$dojo = $entityManager->find('Dojo', $dojoId);
	$dojoName = $dojo->getName();
	echo "<tr>";
    echo sprintf("<td>%s</td><td>%s</td><td>%s</td><td>%s</td>", $id, $name, $dojoId, $dojoName);
	echo "</tr>";
}
echo "</table>";

echo "<br /><br />";

echo "<table border='1'>";
echo "<tr><th>id</th><th>name</th></tr>";
foreach ($dojos as $dojo){
	$id = $dojo->getId();
	$name = $dojo->getName();
	echo "<tr>";
    echo sprintf("<td>%s</td><td>%s</td>", $id, $name);
	echo "</tr>";
}
echo "</table>";

?>

and the output:
doctrine_example

references: