Écouteurs Doctrine dans Symfony : agir avant d'enregistrer une entité

Un écouteur Doctrine, dans Symfony, réagit au cycle de vie d'une entité, avant son insertion ou sa mise à jour, quel que soit le code qui l'enregistre.

#[AsEntityListener(event: Events::prePersist, method: 'prePersist', entity: Plat::class)]
final class SlugDuPlat
{
    public function __construct(private readonly SluggerInterface $slugger)
    {
    }

    public function prePersist(Plat $plat, PrePersistEventArgs $args): void
    {
        if (null !== $plat->getSlug()) {
            return; // un slug choisi à la main est respecté
        }
        $plat->setSlug($this->slugger->slug((string) $plat->getNom())->lower()->toString());
    }
}

Un calcul placé dans un contrôleur ne vaut que pour ce contrôleur ; les commandes, les fixtures et les tests l'oublient. Doctrine annonce lui-même ce qu'il fait, prePersist, preUpdate, postRemove, et #[AsEntityListener] branche un service sur un événement et une classe d'entité précise. L'argument $args donne accès au gestionnaire d'entités, getObjectManager(), par exemple pour vérifier qu'un slug n'est pas déjà pris. Le piège : un écouteur qui écrase sans condition. Recalculer le slug à chaque insertion remplace aussi ceux choisis à la main, et les adresses déjà partagées répondent 404, sans qu'aucune erreur ne l'annonce.

Les exercices font écrire l'écouteur qui donne à chaque nouveau plat un slug tiré de son nom, sans accents ni doublons, puis, dans une taverne mise à l'envers par Pipin, retrouver pourquoi les liens vers le ragoût partagés par les bardes mènent à une 404.

2 exercices font travailler cette notion, en écrivant du code dans le navigateur.

Dans les parcours

Notions voisines

DébogageÉvénementsDécoration de serviceCache