Эта статья основана на на статье описанной ещё в июле 2012 и проведённого Kyiv Code Sprint в июне 2013. Материал статьи остаётся актульным. Здесь опишем как работает система Event Dispatcher в Drupal 8. Будьте внимательны так как диспетчер в Д8 всеволишь один. Хотя логичнее сделать(для меня) для каждого события свой диспетчер. Наверное это будет сделано в Д9. Так как Д8 производительностью не блестает и подбираеться дата релиза, а работы не початый край. Так же это только начало познаний сложных структур Symfony 2 в Drupal 8.
index.php содержит:
Что такое drupal_container(). Это контейнер инъекций зависимостей, волшебный массив, который содержит объекты. Волшебство которого заключается в инициализации обьектов при запросе на получение. Dependency injection containe - DIC содержит описания классов, аргументы, зависимости. Особеностью также являеться, то что аргументы могут быть дугими элементами(это называеться зависимостями) DIC. Возможно регистрировать свои классы, или фабрики классов. Пример с ядра Drupal 8.
Регистрируем объект, после получим.
Drupal\Core\DependencyInjection\ContainerBuilder::getKernelEventDispatcher
так как данный обьект зарегистрирован как фабрика и у нас указан аргумент, он будет передан метод getKernelEventDispatcher(). Так как объект передаёться “по ссылке” - это означает, что это что-то из вне DIC. В данном случае это сам DIC. DIC называеться контейнером сервисов, и всё что туд ложим называем сервисами по принципу Symfony.
Ядро
HTTP ядро использует события диспетчера при вызове handle():
События
События похожи на ловушки(hooks), но намного сложнее. Мы регистрируем класс с диспетчером, который вызовит метод класса getSubscribedEvents, который зарегистрирует методы/наблюдателей на определенные события. Пример класса ViewSubscriber:
Потому когда события KernelEvents::VIEW отправлено наблюдателям в HttpKernel:
К примеру в контейнере зависимостей иньекций можно просмотреть, как создаётся диспетчер getKernelEventDispatcher где создаётся объект EventDispatcher и присоеденяются подписчики событий.
Вот одни из многих.
И другие.
index.php содержит:
$kernel = drupal_container()->get('httpkernel'); $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response);
Что такое drupal_container(). Это контейнер инъекций зависимостей, волшебный массив, который содержит объекты. Волшебство которого заключается в инициализации обьектов при запросе на получение. Dependency injection containe - DIC содержит описания классов, аргументы, зависимости. Особеностью также являеться, то что аргументы могут быть дугими элементами(это называеться зависимостями) DIC. Возможно регистрировать свои классы, или фабрики классов. Пример с ядра Drupal 8.
$this->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver');
Регистрируем объект, после получим.
$this->get('resolver')Когда вызываеться get(), контейнер инициализирует новый класс и хранит его в контейнере. Потому при повторных вызовах мы получим тот же объект Symfony\Component\HttpKernel\Controller\ControllerResolver.
$this->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher') ->addArgument(new Reference('service_container')) ->setFactoryClass('Drupal\Core\DependencyInjection\ContainerBuilder') ->setFactoryMethod('getKernelEventDispatcher');Код регистрирует обьект, который можно получить
$this->get('dispatcher')При вызове get(), сработает метод
Drupal\Core\DependencyInjection\ContainerBuilder::getKernelEventDispatcher
так как данный обьект зарегистрирован как фабрика и у нас указан аргумент, он будет передан метод getKernelEventDispatcher(). Так как объект передаёться “по ссылке” - это означает, что это что-то из вне DIC. В данном случае это сам DIC. DIC называеться контейнером сервисов, и всё что туд ложим называем сервисами по принципу Symfony.
Ядро
HTTP ядро использует события диспетчера при вызове handle():
- KernelEvents::REQUEST - KernelEvents::CONTROLLER - KernelEvents::VIEW - KernelEvents::RESPONSE
События
События похожи на ловушки(hooks), но намного сложнее. Мы регистрируем класс с диспетчером, который вызовит метод класса getSubscribedEvents, который зарегистрирует методы/наблюдателей на определенные события. Пример класса ViewSubscriber:
static function getSubscribedEvents() { $events[KernelEvents::VIEW][] = array('onView'); return $events; }
Потому когда события KernelEvents::VIEW отправлено наблюдателям в HttpKernel:
$this->dispatcher->dispatch(KernelEvents::VIEW, $event);Метод onView будет вызван с аргументом $event. Все подписчики получают единственный объект $event, который содержит только setters и getters.
К примеру в контейнере зависимостей иньекций можно просмотреть, как создаётся диспетчер getKernelEventDispatcher где создаётся объект EventDispatcher и присоеденяются подписчики событий.
Вот одни из многих.
$dispatcher->addSubscriber(new LegacyRequestSubscriber());
И другие.
Про EventDispatcher можете прочитать больше на рессурсе Symfony http://symfony.com/doc/current/components/event_dispatcher/introduction.html . Для меня данный паттерн является составным (Наблюдатель, стратегия, построитель). Хотя для использования компонент является гибким.
ОтветитьУдалитьНеобходимо отметить, то что drupal_container заменен на Drupal::service
ОтветитьУдалитьhttps://api.drupal.org/api/drupal/core!includes!bootstrap.inc/function/drupal_container/8