9.12. Event Dispatcher, prilagođeni kod za određene događaje
Sistem događaja omogućava kreiranje složenijih sistema sa mogućnošću menjanja funkcionalnosti pomoću prilagođenog koda za određene događaje. Mnogi hook-ovi iz Drupala 7 su zamenjeni događajima. Ovo je omogućilo ujedinjenje rada mnogih delova Drupala i dodatnih modula. Sam sistem događaja potiče iz Symfony-a i sastoji se od sledećih delova:
Event Subscribers – „Pretplatnici“ na određene događaje su funkcije ili metode koje se izvršavaju na određenim događajima. U kodu je to klasa koja implementira klasu:
\Symfony\Component\EventDispatcher\EventSubscriberInterface
Event Registry – Prikuplja i sortira po redosledu okidanja Event Subscribers. Registar pretplatnika se čuva u Event Dispatcher objektu kao niz ključ-vrednost sa imenom događaja i prioritetom događaja (redosled). Kada je događaj registrovan kao servis, on je dostupan globalno kroz dispatcher.
Event Dispatcher – Mehanizam u kojem se događaj okida i omogućava pozivanje Event Subscribers u pravom trenutku. Najčešće je barem jedan od Event Dispatcher instanci predstavljen kao servis. Klasa Event Dispatcher implementira:
\Symfony\Component\EventDispatcher\EventDispatcherInterface
Event Context – Mnogi događaji zahtevaju specifičan skup podataka koji može biti važan za pretplatnika događaja. To može biti jednostavna vrednost prosleđena pretplatniku događaja ili klasa koja sadrži potrebne podatke. Klasa Event Context nasleđuje klasu:
\Symfony\Component\EventDispatcher\Event
Hajde da pogledamo primere rada sa događajima da bismo razumeli kako to funkcioniše.
Sve primere koda sam dodao na GitHub u modul drupalbook_examples, možete preuzeti modul i dodati ga na svoj sajt:
https://github.com/levmyshkin/drupalbook8
Drupal 8 više nema hook_init():
https://www.drupal.org/node/2013014
Sada se potreban kod može izvršiti prilikom učitavanja stranice pomoću Event Subscriber-a:
datoteka: modules/custom/drupalbook_examples/drupalbook_examples.services.yml
services:
drupalbook_examples.event_subscriber:
class: Drupal\drupalbook_examples\EventSubscriber\DrupalbookExamplesSubscriber
tags:
- {name: event_subscriber}
Da biste povezali Event Subscriber, potrebno je dodati servis u fajl modula *.services.yml. Ovde opisujemo koju klasu će Event Subscriber koristiti i u tagovima navodimo event_subscriber. Sada treba da kreiramo klasu event subscriber-a:
datoteka: 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;
}
}
Glavne tačke ovog koda su sledeće: klasa event subscriber-a implementira interfejs EventSubscriberInterface, a njegova glavna metoda getSubscribedEvents() određuje na koje događaje će subscriber reagovati i koje metode će pozvati kada se dogode. U našem slučaju, događaj se dešava na samom početku rada Drupala nakon obrade zahteva. Tada se poziva metoda checkForRedirection(). Ako postoji parametar redirect-me u zahtevu, korisnik se preusmerava na početnu stranicu.
Ovaj kod će raditi svaki put kada se učita stranica, ili skoro uvek. Međutim, ako je stranica keširana, može biti poslužena iz keša i Drupal neće izvršavati sav kod, već će odmah poslužiti keširani sadržaj.
U tom slučaju, možete koristiti analog hook_boot(), koji kao i hook_init(), više nije prisutan u Drupalu 8:
https://www.drupal.org/node/1909596
Dodajmo još jednu metodu redirectBeforeWithoutCache() u istu klasu:
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;
}
}
U metodi getSubscribedEvents() registrovali smo oba odgovora na događaj KernelEvents::REQUEST, ali drugoj metodi smo dali prioritet 300, što omogućava da se ona pozove pre ostalih metoda za isti događaj koje imaju niži prioritet. Tako sada preusmerenje radi čak i za keširane stranice.
U Drupalu postoji mnogo događaja na koje se možete pretplatiti, više primera i informacija možete pronaći u zvaničnoj dokumentaciji: