9.12. Միջոցառումների դիսպետչեր, որոշակի միջոցառումների համար նախատեսված հատուկ կոդ
Իրադարձությունների համակարգը թույլ է տալիս կառուցել ավելի բարդ համակարգեր՝ հնարավորությամբ փոխել ֆունկցիոնալությունը որոշակի իրադարձությունների համար սեփական կոդի միջոցով։ Drupal 7-ում եղած շատ hook-եր փոխարինվել են իրադարձություններով։ Սա հնարավորություն է տվել միավորել Drupal-ի բազմաթիվ մասերի և լրացուցիչ մոդուլների աշխատանքը։ Իրադարձությունների համակարգը գալիս է Symfony-ից և բաղկացած է հետևյալ բաղադրիչներից՝
Event Subscribers - «Բաժանորդագրված» մեթոդներ կամ ֆունկցիաներ, որոնք գործարկվում են որոշակի իրադարձությունների դեպքում։ Կոդում սա դաս է, որը իրականացնում է՝
\Symfony\Component\EventDispatcher\EventSubscriberInterface
Event Registry - Հավաքում և դասավորում է Event Subscriber-ներին՝ իրենց գործարկման հերթականությամբ։ Այս registry-ն պահվում է Event Dispatcher օբյեկտում՝ որպես իրադարձության անվան և առաջնահերթության զույգերի զանգված։ Երբ իրադարձությունը գրանցվում է որպես ծառայություն, ապա այն դառնում է գլոբալ մատչելի dispatcher։
Event Dispatcher - Մեխանիզմ, որը գործարկում է իրադարձությունը և կանչում համապատասխան Event Subscriber-ները անհրաժեշտ պահին։ Հիմնականում Event Dispatcher դասի առնվազն մեկ նմուշ հասանելի է որպես ծառայություն։ Դասը իրականացնում է՝
\Symfony\Component\EventDispatcher\EventDispatcherInterface
Event Context - Շատ իրադարձություններ պահանջում են տվյալների որոշակի փաթեթ, որը կարող է կարևոր լինել subscriber-ի համար։ Սա կարող է լինել պարզ արժեք կամ դաս, որը պարունակում է անհրաժեշտ տվյալներ։ Այս դասը ժառանգում է՝
\Symfony\Component\EventDispatcher\Event
Եկեք դիտենք օրինակներ իրադարձությունների հետ աշխատանքի, որպեսզի պարզ լինի, թե ինչպես է այն աշխատում։
Ես ամբողջ կոդը ավելացրել եմ GitHub-ում՝ drupalbook_examples մոդուլում։ Կարող եք ներբեռնել և տեղադրել ձեր կայքում՝
https://github.com/levmyshkin/drupalbook8
Drupal 8-ում այլևս չկա hook_init()՝
https://www.drupal.org/node/2013014
Այժմ էջի բեռնման ժամանակ անհրաժեշտ կոդը կարող եք գործարկել Event Subscriber-ի միջոցով՝
modules/custom/drupalbook_examples/drupalbook_examples.services.yml
services:
drupalbook_examples.event_subscriber:
class: Drupal\drupalbook_examples\EventSubscriber\DrupalbookExamplesSubscriber
tags:
- {name: event_subscriber}
Event Subscriber-ը միացնելու համար անհրաժեշտ է ծառայությունը ավելացնել *.services.yml ֆայլում։ Այստեղ նշում ենք այն դասը, որը հանդիսանում է subscriber և ավելացնում ենք event_subscriber պիտակը։ Հիմա պետք է ստեղծենք Event Subscriber դասը՝
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;
}
}
Դիտարկենք այս կոդի հիմնական կետերը։ Մեր subscriber-ի դասը իրականացնում է EventSubscriberInterface ինտերֆեյսը, որի հիմնական մեթոդը getSubscribedEvents() է։ Այս մեթոդը սահմանում է, թե որ իրադարձություններին պետք է արձագանքի subscriber-ը և ինչ մեթոդներ պետք է կանչի։ Մեր դեպքում, իրադարձությունը տեղի է ունենում Drupal-ի աշխատանքի ամենասկզբում՝ հարցման մշակման ժամանակ։ Եթե տեղի ունենա իրադարձություն, կկանչվի checkForRedirection() մեթոդը։ Այդ մեթոդում ստուգում ենք, թե հարցման մեջ կա redirect-me պարամետրը, և եթե կա՝ կատարում ենք վերաուղղում։
Այս կոդը կգործի գրեթե միշտ՝ էջը բեռնելիս։ Բայց եթե էջը կաշավորված է (cached), ապա կարող է վերադարձվել cache-ից և Drupal-ը չի կատարի այդ կոդը։
Այս դեպքում կարելի է օգտագործել hook_boot() hook-ի անալոգը, որը նույնպես հեռացվել է Drupal 8-ից՝
https://www.drupal.org/node/1909596
Եկեք ավելացնենք redirectBeforeWithoutCache() մեթոդը՝
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;
}
}
getSubscribedEvents() մեթոդում մենք գրանցել ենք նույն KernelEvents::REQUEST իրադարձության արձագանքը, սակայն այս անգամ որոշել ենք առաջնահերթությունը՝ 300։ Սա թույլ է տալիս, որ այս մեթոդը գործի ավելի շուտ, քան մյուս նույն իրադարձության համար կանչվող մեթոդները։ Այժմ վերաուղղումը կգործի նաև cache-ից վերադարձվող էջերի դեպքում։
Drupal-ում կան բազմաթիվ իրադարձություններ, որոնք կարող եք գրանցել որպես Subscriber, ավելի շատ օրինակներ կարող եք գտնել պաշտոնական փաստաթղթերում՝