 
		
											Обзор системы событий в 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. На примере базовой структуры модуля увидели, как это делается на практике. Не стесняйтесь делиться своим мнением или задавать вопросы в разделе комментариев ниже.
Спасибо, что читаете нас!
 
				 
			 
															 
															 
															 
															 
															 
															 
															 
															 
			 
			 
			