Войти

Что вас интересует?

Прослушивание Событий в Битрикс

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

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

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

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

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

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

  • Callback (php callable тип для которого будет выполнено call_user_func_array)
  • php файл (путь к файлу: TO_PATH - относительный, FULL_PATH абсолютный)

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

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

Помимо способов подписки на события существуют типы событий: старого ядра и нового ядра. Обработчики событий старого ядра - принимают сколько угодно аргументов, передаваемых по значению или по ссылке и могут ожидать чего-угодно в результате своей работы. Например уже упомянутое событие OnBeforeCrmDealAdd модуля crm принимает массив полей добавляемого элемента по ссылке, а это значит что его можно изменить. Другой пример событие OnAfterCrmDealAdd, которое не обращает и не обрабатывает возвращаемый результат.

Обработчики событий нового ядра - принимают ровно один аргумент - наследник класса \Bitrix\Main\Event и ожидают возврата \Bitrix\Main\EventResult объекта (допустим null/void).

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

$eventManager = \Bitrix\Main\EventManager::getInstance();
И один из перечисленных методов подписки:
  1. Сигнатура метода добавления обработчика событий нового ядра:
    $eventManager->addEventHandler(
    	$fromModuleId,
    	$eventType,
    	$callback,
    	$includeFile = false,
    	$sort = 100
    ): int

    Пояснения аргументов:

    • $fromModuleId - идентификатор модуля-источника события
    • $eventType - событие на которое мы подписываемся
    • $callback - callable обработчик событий (или null, если обработка файлом)
    • $includeFile - false|string путь к файлу - обработчика (если указан $callback - false)
    • $sort - порядок вызова (меньше - раньше)

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

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

  3. Сигнатура метода регистрации обработчка событий нового ядра:

    $registerEventHandler->registerEventHandler(
    	$fromModuleId,
    	$eventType,
    	$toModuleId,
    	$toClass = '',
    	$toMethod = '',
    	$sort = 100,
    	$toPath = '',
    	$toMethodArg = []
    );

    Пояснения аргументов:

    • $fromModuleId - идентификатор модуля-источника события
    • $eventType - событие на которое мы подписываемся
    • $toModuleId - идентификатор модуля, который подписывается
    • $toClass - класс выполняющий обработку (для callback-обработчика, если файловый - пустая строка)
    • $toMethod - метод класса выполняющий обработку (для callback-обработчика, если файловый - пустая строка)
    • $sort - порядок вызова (меньше - раньше)
    • $toPath - относительный (относительно DOCUMENT_ROOT путь к файлу-обработку, для callback - пустая строка)
    • $toMethodArg - дополнительные аргументы передаваемые callback обработчик или доступные в $args переменной файлового обработчика
  4. Сигнатура метода регистрации обработчика событий старого ядра отличается от нового ядра только названием метода: registerEventHandlerCompatible

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

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

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

Однако в соответствии с оговоренной ранее структурой папки local размещать код обработчика вместе с кодом подписки не следует во избежание раздувания файла с подписками. Наиболее практичный вариант в данном случае: разделение кода-обработчика и кода подписчика.

Например для нашей структуры папки local разделим указанный выше фрагмент.

В файле local/php_interface/events.php:

$eventManager->addEventHandlerCompatible(
    'crm',
    'OnAfterCrmDealAdd',
    [
    	"\\Vendor\\Subsystem\\Integration\\Crm\\DealCatcher",
    	"handleAfterDealAdd"
    ]
): void;

В файле local/php_interface/classes/Vendor/Subsystem/Integration/Crm/DealCatcher.php:

namespace Vendor/Subsystem/Integration/Crm;

class DealCatcher
{
	/**
	 * Handle crm::OnAfterCrmDealAdd event
	 *     - do something with something
	 *     
	 * @param  array &$fields Some deal fields
	 * @return void
	 */
	public static function handleAfterDealAdd( array &$fields ): void
	{
		// ... Do what you need
	}
}
 Обратите внимание на следующие моменты:
  1. Поскольку мы использовали callback-обработчик мы явно обозначили метод handleAfterDealAdd статическим.
  2. Если мы этого не сделаем, то на php 8+ мы получим фатальную ошибку should not be called statically in Мы добавили php-doc комментарий к методу обработчику: указали какое событие он обрабатывает и что он делает

  3. Комментарий к аргументу $fields - Some deal fields - это именно некоторые поля которые было добавлены к сделке, а не все поля сделки. Событие не гарантирует что вам придет полный набор полей и вам всегда нужно проверять есть ли поле с кодом ... в $fields.
  4. Мы явно указали типы аргументов которые мы ждем.
Комментрии
Комементариев нет, будьте первыми....
Оставить комментарий
Пожалуйста, введите ваше Имя.
Пожалуйста, введите ваш Email.
Пожалуйста, напишите комментарий.