Formations aurelearn

Création des entités

N’hésitez pas à créer vos entités à l’aide du wizard de Symfony, en faisant :

shell

# Avec just
just console make:entity
# Sans just
docker compose run --rm symfony console make:entity

Créez une autre classe dans le dossier src/Entity appelée AsbtractEntity.php (voir le modèle ↗). Cette classe renfermera l’ensemble des champs qui seront partagés par toutes les entités de votre application.

De manière générale, ils sont au nombre de 4 :

  • id qui sert d’index en interne pour des requêtes SQL rapides
  • uuid qui sert de référence publique pour ne pas divulguer l’id aux visiteurs via l’URL
  • createdAt qui stocke la date de création
  • updatedAt qui stocke la dernière date de modification

Vous pourriez également avoir deux champs supplémentaires, createdBy et updatedBy, qui permettraient de stocker les utilisateurs ayant fait la création et la dernière modification de cette entité, et qui seraient des relations en ManyToOne vers l’entité User.

Partager les propriétés en commun dans une entité abstraite

Comme expliqué juste au-dessus, nous avons généralement au moins 4 champs communs à toutes les entités. Il paraît alors logique de créer une entité abstraite qui renfermera ces champs, et que toutes les entités pourront hériter.

Pour cela, créez une nouvelle classe src/Entity/AbstractEntity.php avec le contenu suivant :

AbstractEntity.php

<?php
declare(strict_types=1);
namespace App\Entity;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
#[ORM\HasLifecycleCallbacks]
class AbstractEntity
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: Types::INTEGER)]
protected int $id;
#[ORM\Column(type: UuidType::NAME, unique: true)]
protected Uuid $uuid;
#[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
protected \DateTimeImmutable $createdAt;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
protected \DateTimeInterface $updatedAt;
public function __construct()
{
$this->uuid = Uuid::v7();
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTime();
}
#[ORM\PreUpdate]
public function preUpdate(): void
{
$this->updatedAt = new \DateTime();
}
public function getId(): int
{
return $this->id;
}
public function getUuid(): Uuid
{
return $this->uuid;
}
public function getCreatedAt(): \DateTimeImmutable
{
return $this->createdAt;
}
public function getUpdatedAt(): \DateTimeInterface
{
return $this->updatedAt;
}
}

Voici quelques explications sur ce fichier.

Les types de colonne

Par défaut, lorsque vous passez par le maker pour créer vos entités, les types de colonne seront normalement marqués en dur. Il existe pourtant un type fourni par Doctrine qui référence l’ensemble des types disponibles : Doctrine\DBAL\Types\Types. Pensez à utiliser le type, car si le nom en dur change dans une nouvelle version de Doctrine, le type restera lui le même.

DatetimeInterface & DateTimeImmutable

Lorsque vous travaillez avec des dates dans vos applications, différenciez bien DateTimeInterface et DateTimeImmutable :

  • une propriété de type DateTimeImmutable n’a pas vocation à changer dans le temps (ex: createdAt)
  • une propriété de type DateTimeInterface peut éventuellement changer dans le temps : (ex: updatedAt)

Le constructeur

Certaines propriétés de nos entités peuvent être attribuées automatiquement à leur création. C’est par exemple le cas de l’uuid ou de la date de création. Pour cela, nous pouvons les spécifier dans le __construct de l’entité :

AbstractEntity.php

public function __construct()
{
$this->uuid = Uuid::v7();
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTime();
}

Les événements Doctrine

Il est également possible de déclencher des fonctions lorsque certains événements se passent au sein d’une entité :

Pour que ces événements soient déclenchés au sein de notre entité, nous devons lui ajouter un attribut spécial :

AbstractEntity.php

use Doctrine\ORM\Mapping as ORM;
#[ORM\HasLifecycleCallbacks]
class AbstractEntity
{
...
}

Dans notre cas, nous souhaitons mettre à jour la date de modification à chaque mise à jour de l’entité, donc nous allons utiliser l’événement preUpdate :

AbstractEntity.php

use Doctrine\ORM\Mapping as ORM;
#[ORM\PreUpdate]
public function preUpdate(): void
{
$this->updatedAt = new \DateTime();
}

Les getters & setters

Les getters et setters sont le moyen d’accéder à une propriété ou la modifier en dehors de la classe, dans le cas où cette dernière est private ou protected. Doctrine les utilise abondamment pour hydrater les retours de requête SQL par exemple.

Mais il faut les utiliser avec précaution, car certaines propriétés ne doivent pas avoir de setters puisqu’elles sont définies automatiquement. C’est le cas ici de nos propriétés présentes dans AbstractEntity, nous leur attribuons alors seulement un getter.

© 2023 • Aurélien Devaux