Полный цикл в digital

События

Иногда бывает необходимо повлиять на ход выполнения какого-нибудь процесса, а поскольку изменять ядро продукта запрещено в системе реализован механизм событий. В ходе выполнения некоторых API функций или частях системы, в определенных точках установлены вызовы определённых функций, так называемых обработчиков события.

Событие, это сообщение программного обеспечения либо его части, которое указывает, что произошло. Обработчик события — код который исполняется для обработки события

Само событие описывается тремя ключевыми составляющими:

  1. Модуль, являющийся источником события
  2. Название события
  3. Параметры события (аргументы события)

Например, событие OnPageStart модуля main не имеет параметров события, а просто оповещает что происходит начало выполнения пользовательского кода, а событие OnBeforeCrmDealAdd модуля crm передает параметр содержащий поля добавляемой сделки.

Как это работает

В разрезе продукта существует глобальный метод \Bitrix\Main\EventManager, который хранит все зарегистрированные обработчики событий. Некоторый код инициирует отправку события, EventManager выполняет поиск всех обработчиков удовлетворяющих условиям поиска и последовательно в порядке приоритетов и добавления обработчиков передает его в функцию-обработчик события.

Что может выступать обработчиком события?

  • Callback функция
  • php файл с кодом

Как подписаться на события

Существует 2 способа подписки на события: регистрация и добавление.

  1. Регистрация обработчика событий осуществляется обычно при модульной разработке, в таком случае все события добавляются в базу данных, таблица называется b_module_to_module, добавление необходимо сделать один раз при инсталяции модуля
  2. Добавления обработчика событий, осуществляется в ходе выполнения программы и существует только в рамках исполняемого скрипта, скрипт закончил исполнение, соответственно программа в целом забыла про событие

Помимо способов подписки на события существуют типы событий: старого ядра и нового ядра.

  1. Обработчики событий старого ядра, принимают сколько угодно аргументов, передаваемых по значению или по ссылке и могут ожидать чего-угодно в результате своей работы. Например, уже упомянутое событие OnBeforeCrmDealAdd модуля crm принимает массив полей добавляемого элемента по ссылке, а это значит что его можно изменить. Другой пример событие OnAfterCrmDealAdd, которое не обращает и не обрабатывает возвращаемый результат
  2. Обработчики событий нового ядра, принимают ровно один аргумент, наследник класса \Bitrix\Main\Event и ожидают возврата \Bitrix\Main\EventResult объекта, допустим null/void

Регистрация обработчика

Регистрация обработчика событий новое ядро

Для подписки на события необходимо получить инстанс класса EventManager:

$registerEventHandler = \Bitrix\Main\EventManager::getInstance();
$registerEventHandler->registerEventHandler(
        // идентификатор модуля-источника события
	$fromModuleId,
        // событие на которое мы подписываемся
	$eventType,
        // идентификатор модуля, который подписывается
	$toModuleId,
        // класс выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toClass = '',
        // метод класса выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toMethod = '',
        // порядок вызова, чем меньше цифра, тем раньше выполнится
	$sort = 100,
        // относительный путь к файлу-обработчику, относительно DOCUMENT_ROOT, для callback будет пустая строка
	$toPath = '',
        // дополнительные аргументы передаваемые callback обработчик или доступные в $args переменной файлового обработчика
	$toMethodArg = []
);
Регистрация обработчика событий старое ядро

Сигнатура метода регистрации обработчика событий старого ядра отличается от нового ядра только названием метода: registerEventHandlerCompatible

$registerEventHandler->registerEventHandlerCompatible(
        // идентификатор модуля-источника события
	$fromModuleId,
        // событие на которое мы подписываемся
	$eventType,
        // идентификатор модуля, который подписывается
	$toModuleId,
        // класс выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toClass = '',
        // метод класса выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toMethod = '',
        // порядок вызова, чем меньше цифра, тем раньше выполнится
	$sort = 100,
        // относительный путь к файлу-обработчику, относительно DOCUMENT_ROOT, для callback будет пустая строка
	$toPath = '',
        // дополнительные аргументы передаваемые callback обработчик или доступные в $args переменной файлового обработчика
	$toMethodArg = []
);

Добавления обработчика

Добавления обработчика событий новое ядро

Для подписки на события необходимо получить инстанс класса EventManager:

$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler(
    // идентификатор модуля-источника события
    $fromModuleId,
    // событие на которое мы подписываемся
    $eventType,
    // callable обработчик событий, или null если обработка файлом
    $callback,
    // путь к файлу - обработчика, если указан $callback значит пишем false
    $includeFile = false,
    // порядок вызова, чем меньше цифра, тем раньше выполнится
    $sort = 100
)

В качестве возвращаемого значения методов добавления обработчика событий, возвращается порядковый номер этой регистрации, нужен для отписывания от события.

Добавления обработчика событий старое ядро

Сигнатура метода добавления обработчика событий старого ядра, отличается от нового ядра только названием метода addEventHandlerCompatible

$eventManager->addEventHandlerCompatible(
    // идентификатор модуля-источника события
    $fromModuleId,
    // событие на которое мы подписываемся
    $eventType,
    // callable обработчик событий, или null если обработка файлом
    $callback,
    // путь к файлу - обработчика, если указан $callback значит пишем false
    $includeFile = false,
    // порядок вызова, чем меньше цифра, тем раньше выполнится
    $sort = 100
)

Применение

Если мы не разрабатываем модуль и хотим подписаться на событие OnAfterCrmDealAdd модуля crm, то у нас получиться следующий код:

$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->addEventHandlerCompatible(
    'crm',
    'OnAfterCrmDealAdd',
    function( &$arFields )
    {
        // ...
    }
);

Как отписаться от события

Подобно подписке на события существует механизм отписки который обычно используется в двух случаях:

  1. Удаление модуля, когда нужно удалить все зарегистрированные события
  2. Выключение обработчика, когда обработчик события нужен в конкретном месте для конкретного действия и более не требуется
Удаление зарегистрированного обработчика событий
$registerEventHandler->unRegisterEventHandler(
        // идентификатор модуля-источника события
	$fromModuleId,
        // событие на которое мы подписываемся
	$eventType,
        // идентификатор модуля, который подписывается
	$toModuleId,
        // класс выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toClass = "",
        // метод класса выполняющий обработку для callback-обработчика, если файловый значит пустая строка
	$toMethod = "",
        // относительный путь к файлу-обработчику, относительно DOCUMENT_ROOT, для callback будет пустая строка
	$toPath = "",
        // дополнительные аргументы передаваемые callback обработчик или доступные в $args переменной файлового обработчика
	$toMethodArg = []
)
Удаление обработчика событий
$registerEventHandler->removeEventHandle (
        // идентификатор модуля-источника события
	$fromModuleId,
        // событие на которое мы подписываемся
	$eventType,
        // идентификатор обработчика события в списке зарегистрированных обработчиков (то число которое вернул метод addEventHandler или addEventHandlerCompatible
	$iEventHandlerKey
)

Создание своих событий

В продукте существует возможность дополнять свой код собственными событиями.

Для этого в своем коде нужно создать объект-события \Bitrix\Main\Event и отправить его на обработку, метод send на объекте события, а затем по желанию обработать результат.

Пример подписки на события из документации Битрикса:

event = new \Bitrix\Main\Event("mymodule", "OnMacrosProductCreate",array($basketId));

$event->send();

if ($event->getResults())
{
	foreach($event->getResults() as $evenResult)
	{
		if ( $evenResult->getResultType() == \Bitrix\Main\EventResult::SUCCESS )
		{
			$arMacros["PRODUCTS"] = $evenResult->getParameters();
		}
	}
}

Несколько советов по созданию свои собственных событий:

  1. К названию события подойдите максимально осознанно. Не следует создавать по событию на каждый чих — старайтесь группировать их по смыслу
  2. Обрабатывайте все результаты обработчиков. В приведенном примере, если несколько обработчиков будет установлено одному событию, то в массиве $arMacros["PRODUCTS"] будет результата последнего успешно завершенного обработчика
  3. В параметрах события старайтесь передавать объекты. Все объекты в php передаются по ссылке, а значит каждый обработчик будет иметь доступ к последнему актуальному состоянию. Передача скалярных значений и массивов осуществляется по значению, т.е. изменить их в обработчиках будет нельзя

Отладка собственных событий

Иногда возникает необходимость в отладке собственных событий, но не имеет смысла собирать информацию со всей системы. Именно для таких ситуаций в каждом объекте события присутствует 2 дополнительных свойства:

  • debugMode обозначающий, что событие работает в режиме отладки
  • debugInfo массив произвольной информации, которой можно получить через метод getDebugInfo

Что нужно, чтобы добавить отладку в свой код?

Перед отправкой события необходимо включить отладку
$event->turnDebugOn();
$event->send();
После отправки события в любом месте пока существует $event, необходимо вызвать получение отладочной информации
$debugInfo = $event->getDebugInfo();

$debugInfo будет содержать массив любой информации которую туда добавят обработчики.

В нужных местах обработчиков добавить запись полезной информации
$event->addDebugInfo($ar);

В данном случае на $ar не накладывается никаких ограничений. Это может быть объект, скаляр, массив или любая другая информация которая будет добавлена в ходе выполнения обработчиков событий.

Важное примечание: добавлять туда параметры самого события, обработчик или результат обработки НЕ нужно — эти записи уже будут внесены EventManager-классом. Вы можете дополнить их своими техническими параметрами в ходе своего обработчика для ясности.

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!