Doctrine est une librairie puissante qui simplifie la gestion des interactions entre une application et une base de données. En tant qu’ORM (Object-Relational Mapping), elle est intégrée nativement dans Symfony et constitue une solution privilégiée pour la manipulation des données.
ORM
Un ORM (Object-Relational Mapping) établit une correspondance entre les classes d’un langage orienté objet (comme PHP) et les tables d’une base de données relationnelle. Avec Doctrine, une fois ce mapping réalisé, vous pouvez manipuler des objets PHP comme des entités pour interagir avec les données stockées dans la base.
Avantages de l’utilisation d’un ORM comme Doctrine :
- Abstraction : Plus besoin d’écrire des requêtes SQL pour effectuer des opérations courantes (CRUD : Create, Read, Update, Delete).
- Gain de temps : Doctrine simplifie la gestion des relations entre les entités (one-to-one, one-to-many, many-to-many).
- Portabilité : Compatible avec plusieurs systèmes de gestion de bases de données (MySQL, PostgreSQL, SQLite, etc.).
- Évolutivité : Doctrine génère automatiquement le schéma des tables à partir des entités, ce qui facilite les modifications du modèle.
Architecture de Doctrine
Doctrine est constitué de plusieurs couches distinctes, chacune jouant un rôle précis dans le processus de gestion des données.
a. DBAL (Database Abstraction Layer)
La couche DBAL est responsable de la communication directe avec la base de données. Elle agit comme un pont, transmettant des requêtes et récupérant des résultats. Comparable à l’extension PHP PDO, la DBAL est une version plus avancée qui ajoute des fonctionnalités comme :
- La gestion des transactions.
- Le support des types de données spécifiques à Doctrine.
- L’abstraction des requêtes SQL.
Exemple avec DBAL :
$conn = $entityManager->getConnection();
$stmt = $conn->prepare('SELECT * FROM user');
$stmt->execute();
$results = $stmt->fetchAllAssociative();
b. Entité
Une entité est une classe PHP représentant une table dans la base de données. Chaque attribut d’une entité correspond à une colonne de la table, et chaque instance de cette classe représente une ligne.
Caractéristiques d’une entité :
- Les attributs sont privés (encapsulation).
- Les méthodes getter et setter permettent de lire et écrire les données.
- Doctrine s’appuie sur ces méthodes pour gérer les interactions avec la base.
Exemple d’entité :
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class User
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/** @ORM\Column(type="string", length=255) */
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
c. ORM
La couche ORM se situe entre l’application et la DBAL. Son rôle est double :
- Convertir les données relationnelles de la DBAL en objets PHP (entités).
- Générer les requêtes SQL nécessaires à partir des interactions avec les entités.
Exemple avec l’ORM :
$user = new User();
$user->setName('John Doe');
$entityManager->persist($user);
$entityManager->flush();
Dans cet exemple :
- L’objet
$user
est préparé via la méthodepersist
. - La méthode
flush
enregistre les modifications dans la base en générant et exécutant automatiquement une requête SQL.
La Notion d’Entité
Une entité est la base de travail avec Doctrine. Elle représente une table dans la base et permet de manipuler des données comme des objets.
Structure d’une entité :
- Propriétés privées pour chaque colonne de la table.
- Annotations ou attributs PHP pour configurer le mapping entre les propriétés et les colonnes.
- Méthodes d’accès (getter/setter) pour interagir avec les données.
- Constructeur sans paramètre pour permettre l’instanciation par Doctrine.
Exemple :
Pour une table user
avec les colonnes id
et name
:
/**
* @ORM\Entity()
*/
class User
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/** @ORM\Column(type="string", length=255) */
private $name;
public function getId(): ?int { return $this->id; }
public function getName(): ?string { return $this->name; }
public function setName(string $name): self {
$this->name = $name;
return $this;
}
}
Interagir avec une entité :
Créer un utilisateur :
$user = new User();
$user->setName('Jane Doe');
$entityManager->persist($user);
$entityManager->flush();
Récupérer des utilisateurs :
$users = $entityManager->getRepository(User::class)->findAll();
Mettre à jour un utilisateur :
$user = $entityManager->find(User::class, 1);
$user->setName('John Smith');
$entityManager->flush();
Supprimer un utilisateur :
$entityManager->remove($user);
$entityManager->flush();
- Les entités ne sont pas des services Symfony. Leur cycle de vie est géré par Doctrine, et elles ne sont pas injectées par le Service Container.
- Doctrine génère les schémas des bases de données à partir des entités, ce qui facilite l’évolution du modèle de données.
- La séparation des couches DBAL et ORM offre une grande flexibilité dans la gestion des données.
Doctrine, en tant qu’ORM, simplifie considérablement les interactions avec les bases de données en permettant de manipuler des objets PHP plutôt que d’écrire des requêtes SQL. Grâce à son architecture modulaire et ses concepts d’entités, de DBAL et d’ORM, il constitue un outil incontournable pour tout développeur Symfony cherchant à gérer ses données de manière efficace et maintenable.