События в Битрикс: AddEventHandler, EventManager и собственные события

Событийная модель Битрикс позволяет добавлять логику в стандартные процессы системы без изменения ядра. Добавить обработчик заказа, перехватить авторизацию, реагировать на изменение инфоблока — всё это через события.

Старый способ: AddEventHandler

// В /local/php_interface/init.php
AddEventHandler('iblock', 'OnBeforeIBlockElementAdd', function(&$arFields) {
    // Принудительно ставим активность
    $arFields['ACTIVE'] = 'Y';
});

// Обработчик с классом
AddEventHandler('sale', 'OnSaleOrderSaved', ['\\MyModule\\Handlers\\OrderHandler', 'onOrderSaved']);

Новый способ: EventManager D7

use Bitrix\Main\EventManager;
use Bitrix\Main\Event;
use Bitrix\Main\EventResult;

$eventManager = EventManager::getInstance();

$eventManager->addEventHandler(
    'iblock',                         // модуль
    'OnBeforeIBlockElementAdd',       // событие
    function(Event $event) {
        $arFields = $event->getParameter('arFields');
        // логика
        return new EventResult(EventResult::SUCCESS, ['arFields' => $arFields]);
    }
);

Популярные события для переопределения

Модуль Событие Когда
main OnProlog Начало каждого запроса
main OnBeforeUserLogin Перед авторизацией
main OnAfterUserLogin После успешной авторизации
iblock OnBeforeIBlockElementAdd Перед добавлением элемента
iblock OnAfterIBlockElementAdd После добавления элемента
iblock OnBeforeIBlockElementDelete Перед удалением элемента
sale OnSaleOrderSaved Заказ сохранён
sale OnSaleStatusOrderChange Изменение статуса заказа

Создание собственного события

use Bitrix\Main\Event;
use Bitrix\Main\EventManager;

// Объявляем событие
$event = new Event('mymodule', 'OnBeforeProductExport', [
    'productId' => $id,
    'data'      => &$exportData,
]);
$event->send();

// Проверяем результаты обработчиков
foreach ($event->getResults() as $result) {
    if ($result->getType() === \Bitrix\Main\EventResult::ERROR) {
        throw new \RuntimeException($result->getParameters()['message']);
    }
}

Подписка на собственное событие из другого модуля:

EventManager::getInstance()->addEventHandler(
    'mymodule',
    'OnBeforeProductExport',
    function(\Bitrix\Main\Event $event) {
        $data = $event->getParameter('data');
        $data['extra_field'] = 'значение';
        return new \Bitrix\Main\EventResult(
            \Bitrix\Main\EventResult::SUCCESS,
            ['data' => $data]
        );
    }
);

Регистрация обработчиков в модуле

// /local/modules/mymodule/include.php
use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandlerCompatible(
    'iblock',
    'OnAfterIBlockElementAdd',
    ['\\MyModule\\IblockHandler', 'afterElementAdd']
);

// Класс обработчика
namespace MyModule;
class IblockHandler
{
    public static function afterElementAdd(array $arFields): void
    {
        if ($arFields['IBLOCK_ID'] !== 10) return;
        // обработка
    }
}

Итог

Используйте EventManager D7 для новых проектов — он даёт типизацию и возможность возвращать результаты. AddEventHandler в init.php подходит для простых глобальных обработчиков. Никогда не правьте ядро Битрикс — только через события.