Une des initiatives introduites dans Drupal 8 est le remplacement du mécanisme de hooks par le composant Event dispatcher.
Ceci peut paraître compliqué pour certains développeurs qui ont passé de nombreuses années sur des projets Drupal 7 (ou inférieur) et qui ne maîtrisent pas, forcément, le framework Symfony.
Dans cet article nous allons illustrer ce concept avec des analogies de la vie courante et des exemples de code.
Qu’est ce que l’EventDispatcher?
Ci-dessous une citation (traduite) de la documentation officielle de Symfony.
“Le composant EventDispatcher fournit des outils qui permettent aux composants de votre application de communiquer entre eux en distribuant des événements et en les écoutant.”
Pas très clair… Non ? Pour faire simple, il faut savoir que le système d’Events est constitué des composants suivants :
- Event: qui désigne l’événement d’origine.
- Event Listener ou Event Subscriber: Les acteurs qui veulent intercepter l’événement d’origine (Event)
- Event Dispatcher: le responsable de communication entre les précédents composants.
Maintenant, prenons un exemple de la vie courante. Imaginez qu’après le travail, vous passez au magasin du quartier faire des petites courses. Vous appelez chez vous pour demander si quelqu’un à besoin de quelque chose. Sur le chemin, vous recevez plusieurs SMS et la liste de course s’allonge…
A partir de cet exemple nous pouvons dégager les 3 composants:
- Event: Faire les courses.
- Event Listener ou Event Subscriber: Chez vous
- Event dispatcher: votre smartphone.
Simple ! Non ?
Exemple de code
Maintenant, passons à un exemple un peu plus concret. Le scénario est le suivant : Nous avons un script PHP qui affiche un message. Notre but sera d’intercepter le message et le modifier avant son affichage.
<?php
class ContentToOutput
{
protected $content;
public function __construct(string $content = '')
{
$this->content = $content;
}
public function setContent(string $content)
{
$this->content = $content;
}
public function getContent()
{
return $this->content;
}
}
// ============== MAIN PROGRAM ================= //
// Initialisation du message
$message = new ContentToOutput('hello');
// Interceptor le message ici
// …
// Affichage du message.
echo $message->getContent();
Rien de sorcier, le code ci-dessus ne fait qu’afficher le mot ‘Hello’.
La première étape sera d’installer le composant:
composer require symfony/event-dispatcher
Ensuite il faut créer un Event qu’on appellera BeforeOutputEvent.
// Create an event
class BeforeOutputEvent extends Event
{
const NAME = 'before.output';
protected $content;
public function __construct(ContentToOutput $content)
{
$this->content = $content;
}
public function getOutputContent()
{
return $this->content;
}
}
Maintenant c’est au tour de l’Event Listener (Qui va intercepter le message avant son affichage)
class OutputListener
{
public function onBeforeOutput(BeforeOutputEvent $event)
{
$content = $event->getOutputContent();
$out = $content->getContent();
$content->setContent('Listener (' . $out . ')');
}
}
Le Listener ci-dessus va intercepter le message Hello et le convertir en Listener ( Hello )
Il ne reste plus qu’à modifier le programme principal comme suit :
// ============== MAIN PROGRAM ================= //
// Initialisation du message
$message = new ContentToOutput('hello');
// Initialisation de l’event dispatcher
$dispatcher = new EventDispatcher();
// Enregistrer le listener.
$listener = new OutputListener();
$dispatcher->addListener('before.output', [$listener, 'onBeforeOutput']);
// Dispatch de l’event.
$dispatcher->dispatch(new BeforeOutputEvent($message), BeforeOutputEvent::NAME);
// Affichage du message.
echo $message->getContent();
Vous trouverez les codes complets dans les liens suivants :
Event Listener vs Event Subscriber
Event Listener | Event Subscriber |
Ecoute un seul Event | Peut s’inscrire à plusieurs Events |
Priorité d’exécution définie dans le dispatcher | Priorité d’exécution définie dans l’event Subscriber |