Qu'est-ce que Doctrine?

Doctrine 2 est un mapper objet-relationnel pour PHP 5.3.3+ qui fournis de la persistance transparente pour des objets PHP. La séparation complète de la logique et de la persistance dans un système de stockage relationnel est le but principale.

L'avantage de Doctrine pour un programmeur est de permettre un meilleur focus sur sur la logique objet orienté et de pouvoir considérer la persistance comme un problème secondaire.

Fonctions de Doctrine 2

Les fonctions clés de Doctrine 2 incluent :

  • Prends en charge un grand nombre de base de données via le DBAL.
  • Possibilité de reverse engineer une base de données existante en classes.
  • Supporte les hooks et les événements à différentes étapes dans le code.
  • Joins automatique sur les foreign keys.
  • Polymorphisme sur une seule table avec une colonne pour le type.
  • Possibilité d'utiliser un système de cache comme memcached, SQLite ou APC.
  • Transactions ACID (Atomicité, Consistance, Isolation, Durabilité).
  • Migrations de base de données.
  • Possibilité de compiler plusieurs fichier PHP pour limiter le nombre d'inclusions et augmenter la performance.

Comparaison entre les deux solutions pour PHP

En utilisant MySQLi :

$stmt = $mysqli->prepare('INSERT INTO users (username, password) VALUES (?, ?)');
$stmt->bind_param('s', $username);
$stmt->bind_param('s', $password);
$stmt->execute();
echo $mysqli->insert_id;

En utilisant Doctrine 2 :

$user = new User();
$user->username = $username;
$user->password = $password;
$entityManager->persist($user);
$entityManager->flush();
echo $user->id;

Entities

Classe représentant un objet un stockage persistant.

Annotation en commentaire

Doctrine utilise les commentaires pour permettre au programmeur d'attacher des méta-données aux membres d'une classe afin de contrôler la persistance.

/**
 * @Entity @Table(name="table")
 **/

Les principaux éléments sont:

  • @Entity — Déclare que la classe qui suit est un entity.
  • @Table — Contrôle les propriétés de la table qui accueillera l'entity.
  • @Id — Détermine que la colonne est une clé primaire.
  • @Column — Contrôle la colonne associé au membre de l'objet suivant.
  • @GeneratedValue — Indique que la valeur du champ doit être générée automatiquement.

Propriété @Column

La propriété @Column est une des instructions les plus importantes. Elle comporte un grand nombre d'options :

  • type — Le type de la colonne, beaucoup de type sont supportés.
  • name — Le nom de la colonne.
  • length — La longueur pour les string.
  • unique — Si la valeur de la colonne doit être unique.
  • nullable — Si la colonne peut être null.
  • precision — Précision pour les nombres décimaux.
  • scale — L'envergure pour les nombres décimaux.
  • columnDefinition — Permet de fournir un morceaux de DDL manuel.
  • options — Options passés au driver de base de données.

Exemple de classe entity

/**
 * @Entity @Table(name="users")
 **/
class User
{
    /** @Id @Column(type="integer") @GeneratedValue **/
    protected $id;
    /** @Column(type="string") **/
    protected $username;
    /** @Column(type="string") **/
    protected $password;

    // ...

Les différentes associations

Doctrine supporte tous les scénarios d'associations par l'utilisation de propriétés en commentaire.

  • @OneToOne
  • @OneToMany
  • @ManyToOne
  • @ManyToMany

Dans tous les cas, le paramètres targetEntity est nécessaire et dans les cas ou l'association est bidirectionnelle, mappedBy est nécessaire au propriétaire et inversedBy pour l'autre côté de l'association.

Exemple d'entities avec associations

Dans l'exemple, un Post possède plusieurs Comment, on observe donc une relation One-to-Many.

/**
 * @Entity @Table(name="posts")
 **/
class Post {

  /** @Id @Column(type="integer") @GeneratedValue **/
  protected $id;
  /** @OneToMany(targetEntity="Comment", mappedBy="post") **/
  protected $comments;
/**
 * @Entity @Table(name="comments")
 **/
class Comment {

  /** @Id @Column(type="integer") @GeneratedValue **/
  protected $id;
  /** @ManyToOne(targetEntity="Post", inversedBy="comments") **/
  protected $post;

EntityManager et Repository

Le point d'accès centrale à tout.

L'EntityManager

L'EntityManager est la pièce centrale qui permet d'accéder au système de persistance.

Une installation standard de Doctrine 2 va exposer une variable $entityManager ou similaire pour y permettre l'accès.

Les fonctions membres principales de l'EntityManager sont les suivantes :

  • find('Entity', $id) — Raccourci pour trouver un entity par sa clé primaire.
  • getRepository('Entity') — Récupère une Repository pour effectuer des requêtes sur l'entity désiré.
  • persist($entity) — Enregistre l'entity en question dans la base de données.
  • flush() — Exécute tous les opérations de persistance dans le buffer en attente. flush() doit être exécuté pour commettre les modifications dans la base de données.

Les Repository

L'EntityManager permet l'accès à un objet Repository pour effectuer des requêtes sur les entity en base de données.

$repo = $entityManager->getRepository('Entity');

L'objet expose les fonctions suivantes :

  • findAll() — Récupère tous les entities.
  • find($id) — Trouve un entity par son ID.
  • findBy($condition) — Trouve tous les entities respectant la condition.
  • findOneBy($condition) — Trouve un seul entity respectant la condition.
  • findBy<ColumnName>($value) — Il existe une variante pour chaque colonne dans l'entity. Trouve tous les entities par la valeur d'une colonne.
  • findOneBy<ColumnName>($value) — Il existe une variante pour chaque colonne dans l'entity. Trouve un entity par la valeur d'une colonne.

Persister un objet

Un nouvel entity peut être persisté en base de données par l'EntityManager.

$gab = new Gab();
$gab->money = 31337;
$entityManager->persist($gab);
$entityManager->flush();

Les objets déja en base de données soit récupéré par un Repository ou précédemment persisté sont déjà lié à l'EntityManager et il suffit d'exécuter la méthode flush() pour sauvegarder les changements.

$repo = $entityManager->getRepository('Gab');
$gab = $repo->find(42);
$gab->money = 1337;
$entityManager->flush();

Installation et nouveau projet

Création d'un premier projet avec Dotrine 2.

PHP Composer

Structure d'un projet avec Doctrine 2

La structure et la nomenclature des fichiers joue un rôle très important dans tout projet PHP, mais particulièrement lorsqu'un framework est en jeu.

L'organisation typique d'un projet avec Doctrine 2 est la suivante :

  • MonProjet/
    • public/
    • src/
      • Contient tous les entities.
    • vendor/
      • Contient toutes les dépendances installées par Composer.
    • bootstrap.php
    • cli-config.php
    • composer.json
    • index.php

composer.json

Le fichier composer.json contrôle les dépendances du projet PHP.

{
  "require": {
    "doctrine/orm": "2.4.*"
  },
  "autoload": {
    "psr-0": {
      "": "src/"
    }
  }
}

Il suffit de naviguer en ligne de commande vers le dossier du projet et exécuter la ligne suivante pour installer les dépendances dans le dossier vendor/ :

$ cd MonProjet
$ composer install

bootstrap.php

Le fichier bootstrap.php s'occupe de charger les dépendances et d'initialiser l'EntityManager de Doctrine. Ce fichier devra être inclus une seule fois au tout début de chaque script de page.

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

require_once 'vendor/autoload.php';

// Créé une configuration de type "annotation" avec le chemin vers les "entities".
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__.'/src'), $isDevMode);

// Paramètres de connexion à la base de données.
$conn = array(
    'driver'   => 'pdo_mysql',
    'user'     => 'root',
    'password' => '',
    'dbname'   => 'db'
);

// Création de l'EntityManager, soit le pont entre les objets et la DB.
$entityManager = EntityManager::create($conn, $config);

cli-config.php

Le fichier cli-config.php est utilisé par l'outil en ligne de commande pour identifier les entities et les paramètres de connexion.

use Doctrine\ORM\Tools\Console\ConsoleRunner;

require_once 'bootstrap.php';

return ConsoleRunner::createHelperSet($entityManager);

À ce stade, on peux générer la base de données à partir des entities en utilisant la ligne de commande.

$ cd MonProjet
$ php vendor/bin/doctrine orm:shema-tool:create

Projet tutoriel

Un blog très simple qui met en œuvre les fonctions clés de Doctrine.

Les entities du projet

Comme dans l'exemple d'association, le projet fera usage de deux entity, soit un Post et un Comment.

Définition du Post :

  • Id — int auto-increment
  • Title — string
  • Body — string
  • Comments — Comment[]

Définition du Comment :

  • Id — int auto-increment
  • Body — string
  • Post — Post

Un Post possède plusieurs Comment.

<Merci!>

Informations de contact: