La gestion des événements applicatifs
Concepts et écoute d’événement applicatifs
Le répartiteur d’événements (Event Dispatcher en anglais) est l’un des composants les plus simples du framework. Il est pourtant largement utilisé au sein de celui-ci et est indispensable, c’est un véritable rouage de Symfony.
Le répartiteur d’événements implémente le modèle de conception Observer. Le rôle de ce design pattern est d’autoriser diverses parties à venir observer le déroulement de l’exécution d’un traitement, au travers de points d’ancrage. En fonction des éléments observés sur un point d’ancrage donné, ces diverses parties pourront décider de déclencher certaines actions, voire interagir avec le code observé, et tout cela autour d’un système d’événements.
Savoir utiliser le répartiteur d’événements à bon escient contribue à fortement améliorer la qualité de son code ainsi que sa maintenabilité.
1. La propagation des événements
La description étant assez théorique pour l’instant, nous vous proposons de découvrir ce modèle de conception au travers d’un exemple.
Imaginons un blogueur qui, à chaque nouvel article posté par l’un de ses collaborateurs, souhaite le persister en base de données, envoyer un e-mail de remerciement à l’auteur et poster un tweet.
Le but n’étant pas de développer l’exemple en entier, nous allons présupposer que trois services sont déjà configurés et permettent de réaliser ces tâches : pdo, mailer et twitter.
Voici ce à quoi pourrait ressembler le contrôleur :
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Httpfoundation\Request;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
#[Route('/blog')]
class DefaultController extends AbstractController
{
#[Route('/publier')]
public function publier(Request $request, MailerInterface $mailer)
{ ...
Les événements du Kernel
1. Les différents type d’événements
Le Kernel (noyau en français) de Symfony propage plusieurs événements tout au long du traitement d’une requête :
-
kernel.request : cet événement est dispatché au tout début du traitement de la requête. Il peut être utilisé pour retourner une réponse directement sans passer par la phase de routage, par le contrôleur, etc.
-
kernel.controller : cet événement a lieu juste avant l’exécution du contrôleur.
-
kernel.controller_arguments : cet événement a également lieu avant l’exécution du contrôleur. Grâce à lui, vous pouvez modifier les arguments passés au contrôleur.
-
kernel.view : l’événement kernel.view est dispatché si le contrôleur ne retourne pas une instance de l’objet Response.
-
kernel.response : cet événement permet de modifier l’objet réponse à envoyer au client. Exemple d’utilisation : en environnement de développement, Symfony utilise cet événement pour ajouter la barre de débogage en bas de page.
-
kernel.finish_request : lorsque des sous-requêtes modifient l’état de votre application, cet événement peut...
Les événements de la console
1. Prérequis
Une bonne compréhension de la console Symfony est nécessaire pour appréhender ce chapitre. N’hésitez pas à parcourir les chapitres adéquats (Architecture du framework - La console et Annexes - Créer une commande pour la console) avant de continuer.
2. Les événements
La console est capable de déclencher plusieurs événements, au nombre de trois.
Le premier, console.command, se produit avant l’exécution d’une commande. Si une exception est lancée lors du déroulement de la commande, l’événement console.exception intervient. L’événement console.terminate est finalement déclenché une fois la commande terminée.
Voici comment les différents événements de la console peuvent être intégrés au sein d’un listener :
namespace App\Listener;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
class ConsoleListener implements EventSubscriberInterface
{
public...