Работа с событиями в D7
use Bitrix\Main;
Cистема событий битрикс с легкостью позволяет создавать функционал, который отсутствует в базовой версии.
Представьте пример, что у вас есть магазин, где в автоматическом режиме обновляются данные о ценах на основе данных получаемых из систем поставщиков. Но вы хотите чтобы вместо цен 123руб. 568руб. фигурировали округленные цены 120руб. и 570руб. Для этого мы подписываемся на событие изменения цены и округляем её.
Или же при оформлении заказа мы хотите получать уведомление в Telegram, для этого вам необходимо подписаться на событие создание заказа и отправить его.
Тут мы рассмотрим систему событий ядра d7.
Менеджер событий
Main\EventManager::getInstance()
Это центральный объект системы событий, содержит в себе все данные по обработчикам событий. Когда событие вызывается, он как раз и запускает все обработчики.
Обработка событий
Чтобы получить уведомление о том или ином событии, на него нужно подписаться. Сделать это можно следующим образом:
/**
* Функция
*/
Main\EventManager::getInstance()->addEventHandler(
'module',
'eventName',
'functionName'
);
/**
* Класс - метод
*/
Main\EventManager::getInstance()->addEventHandler(
'module',
'eventName',
['className', 'methodName']
);
Метод addEventHandler()
имеет до пяти аргументов:
- Название модуля, порождающее событие;
- Название самого события;
- Вызываемый код, который может быть использован
call_user_func_array()
; - Подключаемый файл, будет дополнительно подключен (опционально);
- Сортировка, порядок выполнения слушателей, по умолчанию 100 (опционально).
Когда обработчик зарегистрирован, он ждет пока сработает событие. При срабатывании события, вызывается функция из третьего параметра, с одним единственным аргументом в виде объекта Main\Event
. Пример реализации обработки событий в ядре d7
class className
{
public static function methodName(Main\Event $event)
{
/**
* Все переданные параметры
*/
$arParams = $event->getParameters();
/**
* Конкретный параметр
*/
$arFields = $event->getParameter('fields');
$result = new Main\Entity\EventResult();
/**
* Изменение данных
*/
$result->modifyFields(
[
'secondVar' => 'N',
'newVar' => 'val',
]
);
/**
* Удаление данных
*/
$result->unsetField('firstVar');
/**
* Ошибка
*/
if (666 === $arParams['userId']) {
$result->addError(new Main\Entity\EntityError('user is banned', 'ERROR_USER_IS_BAN'));
}
return $result;
}
}
Создание и запуск событий
В D7, по сравнению со старым ядром, снижены требования к данным, которые должен иметь код, порождающий событие. Пример отправки события:
/**
* Без параметров
*/
$event = new Main\Event('module', 'eventName');
$event->send();
/**
* С параметрами
*/
$fields = [
'firstVar' => 'value',
'secondVar' => 'Y',
];
$event = new Main\Event(
'module',
'eventName',
[
'fields' => &$fields,
'user' => 123,
]
);
$event->send();
Конструктор Main\Event
имеет до четырех аргументов:
- Название модуля;
- Название самого события;
- Параметры, передаваемые в событие (опционально) [массив];
- Фильтр с названием модулей (опционально) [массив].
Фильтр, это массив с названием модулей, слушатели которых будут выполнены. Актуально только для зарегистрированных обработчиком модуль — модульMain\EventManager::getInstance()->registerEventHandler();
.
При необходимости есть возможность на стороне, отправляющей событие, получить результат обработки события.
Результатом обработки события будет экземпляр класса Main\EventResult
.
У Main\EventResult
есть наследник Main\Entity\EventResult
который позволяет модифицировать результат.
Обратите внимание, что параметры можно передавать по ссылке &$fields
, и модифицировать напрямую в обработке.
foreach ($event->getResults() as $eventResult) {
switch ($eventResult->getType()) {
case Main\EventResult::ERROR:
/**
* Обработка ошибки
*/
$handlerRes = $eventResult->getParameters();
if ($eventResult instanceof Main\Entity\EventResult) {
/**
* Появляется массив с ошибками
*/
$arErrors = $eventResult->getErrors();
}
break;
case Main\EventResult::SUCCESS:
/**
* Успешно
*/
$handlerRes = $eventResult->getParameters();
if ($eventResult instanceof Main\Entity\EventResult) {
/**
* Появляется возможность модифицировать результат
*/
foreach ($eventResult->getUnset() as $val) {
unset($fields[$val]);
}
$modified = $eventResult->getModified();
if (!empty($modified)) {
$fields = array_merge($fields, $modified);
}
}
break;
case Main\EventResult::UNDEFINED:
/**
* Обработчик вернул неизвестно что вместо объекта класса Main\EventResult
* его результат по прежнему доступен через getParameters
*/
$handlerRes = $eventResult->getParameters();
break;
}
}