9.12. Event Dispatcher, benutzerdefinierter Code für bestimmte Ereignisse
Das Event-System ermöglicht es Ihnen, komplexere Systeme zu erstellen, bei denen die Funktionalität durch benutzerdefinierten Code für bestimmte Ereignisse geändert werden kann. Viele Hooks aus Drupal 7 wurden durch Events ersetzt. Dies ermöglichte eine Vereinheitlichung der Arbeit vieler Teile von Drupal und zusätzlicher Kopiermodule. Das Event-System selbst stammt von Symfony und besteht aus folgenden Teilen:
Event Subscribers – „Abonnenten“ für bestimmte Events sind Funktionen oder Methoden, die bei bestimmten Ereignissen ausgelöst werden. Im Code ist es eine Klasse, die die Schnittstelle implementiert:
\Symfony\Component\EventDispatcher\EventSubscriberInterface
Event Registry – Sammelt und sortiert Event Subscribers entsprechend der Reihenfolge ihrer Auslösung. Das Registry für Subscriber wird als Array mit Schlüssel-Wert-Paaren aus Eventnamen und Priorität im Event Dispatcher Objekt gespeichert. Wenn ein Event als Service registriert ist, ist es als global verfügbarer Dispatcher registriert.
Event Dispatcher – Der Mechanismus, bei dem das Event ausgelöst wird und der es ermöglicht, Event Subscribers zum richtigen Zeitpunkt aufzurufen. Meistens wird mindestens eine Instanz des Event Dispatchers als Service bereitgestellt. Die Event Dispatcher Klasse implementiert:
\Symfony\Component\EventDispatcher\EventDispatcherInterface
Event Context – Viele Events benötigen einen spezifischen Datensatz, der für den Event Subscriber wichtig sein kann. Dies kann ein einfacher Wert sein, der an den Subscriber übergeben wird, oder eine Klasse, die die nötigen Daten enthält. Die Event Context Klasse erweitert die Klasse:
\Symfony\Component\EventDispatcher\Event
Schauen wir uns Beispiele zur Arbeit mit Events an, um zu verstehen, wie das funktioniert.
Ich habe den gesamten Code auf GitHub im Modul drupalbook_examples hinzugefügt, Sie können das Modul herunterladen und auf Ihrer Webseite hinzufügen:
https://github.com/levmyshkin/drupalbook8
Drupal 8 hat den hook_init() nicht mehr:
https://www.drupal.org/node/2013014
Jetzt können Sie den notwendigen Code beim Laden der Seite mit einem Event Subscriber ausführen:
Datei: modules/custom/drupalbook_examples/drupalbook_examples.services.yml
services:
drupalbook_examples.event_subscriber:
class: Drupal\drupalbook_examples\EventSubscriber\DrupalbookExamplesSubscriber
tags:
- {name: event_subscriber}
Um einen Event Subscriber zu verbinden, müssen Sie den Service in der Moduldatei *.services.yml hinzufügen. Hier beschreiben wir, welche Klasse der Event Subscriber sein wird und schreiben den Namen event_subscriber in die Tags. Nun müssen wir die Event Subscriber-Klasse erstellen:
Datei: modules/custom/drupalbook_examples/src/EventSubscriber/DrupalbookExamplesSubscriber.php
<?php
namespace Drupal\drupalbook_examples\EventSubscriber;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class DrupalbookExamplesSubscriber implements EventSubscriberInterface {
public function checkForRedirection(GetResponseEvent $event) {
if ($event->getRequest()->query->get('redirect-me')) {
$event->setResponse(new RedirectResponse(\Drupal::url('<front>', [], ['absolute' => TRUE])));
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkForRedirection');
return $events;
}
}
Sehen wir uns die wichtigsten Punkte dieses Codes an. Die Klasse unseres Event Subscribers implementiert die Schnittstelle EventSubscriberInterface, die Hauptmethode dieser Schnittstelle ist getSubscribedEvents(), die bestimmt, auf welche Events unser Subscriber reagiert und welche Methoden aufgerufen werden, falls das Event eintritt. In unserem Fall wird ein Event ganz am Anfang der Drupal-Arbeit nach der Verarbeitung der Anfrage ausgelöst. Hier rufen wir die Methode checkForRedirection() auf, wenn das Event eintritt. In der Methode selbst wird bei Vorhandensein des Parameters redirect-me eine Weiterleitung zur Startseite (example.com) ausgelöst.
Dieser Code wird immer ausgeführt, wenn Sie eine Seite laden, oder fast immer. Der Grund ist, wenn Ihre Seite zwischengespeichert (cached) ist, wird sie möglicherweise direkt aus dem Cache geliefert und Drupal führt nicht alle Codeabschnitte aus, der Cache arbeitet sofort.
In diesem Fall können Sie den Hook hook_boot() analog verwenden, der wie hook_init() aus Drupal 8 entfernt wurde:
https://www.drupal.org/node/1909596
Fügen wir eine weitere Methode redirectBeforeWithoutCache() hinzu
Datei: modules/custom/drupalbook_examples/src/EventSubscriber/DrupalbookExamplesSubscriber.php:
<?php
namespace Drupal\drupalbook_examples\EventSubscriber;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class DrupalbookExamplesSubscriber implements EventSubscriberInterface {
public function checkForRedirection(GetResponseEvent $event) {
if ($event->getRequest()->query->get('redirect-me')) {
$event->setResponse(new RedirectResponse(\Drupal::url('<front>', [], ['absolute' => TRUE])));
}
}
public function redirectBeforeWithoutCache(GetResponseEvent $event) {
if ($event->getRequest()->query->get('redirect-me')) {
$event->setResponse(new RedirectResponse(\Drupal::url('<front>', [], ['absolute' => TRUE])));
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkForRedirection');
$events[KernelEvents::REQUEST][] = array('redirectBeforeWithoutCache', 300);
return $events;
}
}
In der Methode getSubscribedEvents() haben wir die Reaktion auf dasselbe KernelEvents::REQUEST Event registriert, nur setzen wir diesmal die Priorität auf 300, was erlaubt, dass diese Methode früher ausgeführt wird als Methoden mit niedrigerer Priorität, die für dasselbe Event ausgelöst werden. Nun funktioniert die Weiterleitung auch für eine gecachte Seite.
In Drupal gibt es viele Events, die zu einem Subscriber hinzugefügt werden können. Weitere Beispiele finden Sie in der offiziellen Dokumentation: