Обзор системы событий в Magento 2

События в Magento 2 – это очень гибкий способ расширить логику приложения. В сегодняшней статье мы сделаем краткий обзор системы событий, а также увидим, как это работает в Magento 2.

 

 

Шаблон наблюдателя (observer)

Основная концепция системы событий такая же, как у старого доброго шаблона программирования для наблюдателей: с ее помощью реализуется у класса механизм, который позволяет объекту этого класса получать оповещения об изменении состояния других объектов и тем самым наблюдать за ними. Шаблон Обсервера (Observer) определяет зависимость «один-ко-многим» между объектами так, что при изменении состояния одного объекта, все зависящие от него объекты уведомляются и обновляются автоматически.

Обычно шаблон представлен двумя объектами: Наблюдателем и Субъектом. Сущность Observer (наблюдателя) прослушивает уведомления Субъекта и выполняет некоторые действия после получения уведомления. А Субъект отвечает за уведомления Наблюдателя: он инкапсулирует информацию о зарегистрированных Наблюдателях и информирует их, когда уведомление было запущено.

Это была общая информация для понимания того, как работает шаблон обсервера. А теперь давайте посмотрим, как это работает на практике в Magento 2.

 

 

Система событий в Magento 2

Давайте для практики создадим базовую структуру нашего модуля для обсервера следующим образом:

/{ПАКЕТ_МОДУЛЕЙ}/{МОДУЛЬ}/etc/events.xml  /{ПАКЕТ_МОДУЛЕЙ}/{МОДУЛЬ}/Observer/ObserverClass.php  

 

Затем для наблюдения за событиями нам нужно объявить нашего наблюдателя. Объявите наблюдателей и событие в файле events.xml. В новой версии Magento загрузка конфигурации может относиться к различным областям. Все области представлены в виде папок в каталоге etc, и можно указать конфигурацию events.xml для следующих областей:

  • adminhtml – конфигурация будет применена для панели администратора.
  • frontend – конфигурация будет применена для витрины.
  • crontab – конфигурация будет применена для действий CRON.
  • webapi_rest – конфигурация будет применена, когда Magento используется как приложение REST.
  • webapi_soap – конфигурация будет применена к вызовам SOAP.

 



Все файлы конфигурации, которые находятся в папке etc, используются в глобальной области. Глобальные конфигурации загружаются перед конфигурацией конкретных областей и переопределяют их. Для примера мы создадим конфигурацию events.xml в глобальной области.

 

Давайте посмотрим, как наблюдатели объявляются в events.xml:

<?xml version="1.0"?>  <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">   <event name="unique_name_of_event">    <observer name="global_event_observer_name" instance="{ПАКЕТ_МОДУЛЕЙ}\{МОДУЛЬ}\Observer\ObserverClass" shared="true" />   </event>  </config>  

 

Настройка событий начинается с узла <config>. Здесь атрибуты задают определение XML схемы, которая должна проверять узлы, вложенные в <config>. Узлы событий <event> вложены в узел <config>. В узле <event> объявляются наблюдатели (обсерверы), и этот узел может содержать следующие атрибуты:

  • name – обязательный атрибут, который идентифицирует узел. Он должен быть уникальным, чтобы предотвратить переопределение узла.
  • instance – обязательный атрибут, который указывает полное имя класса, который должен быть подписан на уведомления о событиях.
  • shared – необязательный атрибут, который определяет способ создания класса. Если эта опция не указана (или она имеет false в качестве значения), класс будет создаваться каждый раз, когда происходит событие. В противном случае класс будет разделен между событиями: он будет создан только один раз и сохранен в кеше.
  • disabled – необязательный атрибут, который дает возможность отключить наблюдателя, если он указан как true.

 

Итак, мы объявили наш обсервер. Теперь давайте посмотрим, как он может быть реализован:

<?php  namespace {ПАКЕТ_МОДУЛЕЙ}\{МОДУЛЬ}\Observer;  use Magento\Framework\Event\ObserverInterface;  class ObserverClass implements ObserverInterface  {   public function __construct()   {    // Объявление зависимостей   }   public function execute(\Magento\Framework\Event\Observer $observer)   {    // Код, который нужно выполнить при событии, например:    $request = $observer->getRequest();    …    return $this;   }  }  

 

 

Обратите внимание, что есть одно важное требование: все наблюдатели должны реализовать интерфейс \Magento\Framework\Event\ObserverInterface. В соответствии с этим в методе ObserverInterface::execute() должна быть только одна логика наблюдения. В дальнейшей логике метод получает всю информацию о событии из параметров. Одним из параметров является объект класса \Magento\Framework\Event\Observer. Он может вернуть информацию о событии, используя магические методы (например, геттеры или сеттеры).

 

Наконец, как Magento 2 запускает события? Все менеджеры событий должны быть реализованы из класса Magento\Framework\Event\ManagerInterface:

interface ManagerInterface  {   /**   * Отправка события (dispatch event)   * Вызывает все обратные вызовы наблюдателей, зарегистрированных для этого события   * и других наблюдателей, соответствующих шаблону имени события   *   * @param string $eventName   * @param array $data   * @return void   */   public function dispatch($eventName, array $data = []);  }  

 

 

Ниже вы можете увидеть логику запуска событий для метода Magento\Framework\Event\Manager::dispatch():

class Manager implements ManagerInterface  {   /**   * @param InvokerInterface $invoker   * @param ConfigInterface $eventConfig   */   public function __construct(InvokerInterface $invoker, ConfigInterface $eventConfig)   {    $this->_invoker = $invoker;    $this->_eventConfig = $eventConfig;   }   public function dispatch($eventName, array $data = [])   {    $eventName = mb_strtolower($eventName);    foreach ($this->_eventConfig->getObservers($eventName) as $observerConfig) {     $event = new \Magento\Framework\Event($data);     $event->setName($eventName);     $wrapper = new Observer();     $wrapper->setData(array_merge(['event' => $event], $data));     $this->_invoker->dispatch($observerConfig, $wrapper);    }   }  }  

 

 

Подводя итог, класс менеджера делегирует обработку конфигураций, а наблюдатель делегирует обязанности реализациям интерфейсов ConfigInterface и InvokerInterface соответственно. Кроме того, можно запускать пользовательские события (так же, как и в Magento 1.x). Для этого просто внедрите менеджер событий в свой класс и вызовите метод dispatch() менеджера, когда событие должно быть запущено. Вот пример:

class MyClass  {   public function __construct(ManagerInterface $eventManager)   {    // инъекция зависимостей менеджера событий    $this->_eventManager = $eventManager;   }   public function someMethod()   {    // здесь событие должно быть оправлено    $this->_eventManager->dispatch('my_event', array('context' => $this));   }  }  

 

 

В этой статье мы вкратце рассмотрели, как работает система событий в Magento 2. На примере базовой структуры модуля увидели, как это делается на практике. Не стесняйтесь делиться своим мнением или задавать вопросы в разделе комментариев ниже.

Спасибо, что читаете нас!