Пользовательские обработчики событий в платформе 1С-Битрикс

Раздел: -> Bitrix

Система событий в 1С-Битрикс позволяет расширять функционал без изменения ядра. События можно перехватывать на разных этапах работы модулей: создание, обновление, удаление сущностей, отправка почты, выполнение действий в административной части. Это основа для кастомизации и интеграции.

Основные сценарии использования событий

Как добавить собственный обработчик на событие изменения элемента инфоблока?


// В init.php или в методе InstallEvents модуля
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", array("MyIblockHandler", "onUpdate"));

class MyIblockHandler {
    public static function onUpdate(&$arFields) {
        // $arFields содержит поля элемента после сохранения
        if ($arFields["ACTIVE"] === "Y") {
            // Действия для активного элемента
        }
    }
}

Iblock element edit php (редактирование элемента инфоблока)

Обработчик регистрируется с помощью AddEventHandler. Первый аргумент - модуль, второй - имя события, третий - callback (метод статического класса). Обработчик получает массив полей элемента, изменения в котором можно вносить напрямую. Размещать код лучше в файле init.php в корне сайта или в установочном файле модуля.

Типичные ошибки:

  • Обработчик не срабатывает, если код добавлен после инициализации модуля - проверьте порядок подключения файлов.
  • В метод передаётся массив полей, но ключи могут отличаться от ожидаемых - используйте \Bitrix\Iblock\ElementTable::getEntity() для точного списка полей.
  • Изменение полей внутри обработчика не влияет на запись в БД, если не использовать ссылку - обязательно используйте &$arFields.
  • Обработчик может зациклиться, если внутри него снова инициировать то же событие - предусмотрите флаги блокировки.

Как создать почтовое событие для уведомления администратора?


// Регистрируем новый тип почтового события
CEventType::Add(array(
    "LID" => "ru",
    "EVENT_NAME" => "MY_ORDER_CONFIRMED",
    "NAME" => "Заказ подтверждён",
    "DESCRIPTION" => "Уведомление о подтверждении заказа"
));

// Добавляем шаблон письма
$cEventMessage = new CEventMessage;
$arFields = array(
    "ACTIVE" => "Y",
    "EVENT_NAME" => "MY_ORDER_CONFIRMED",
    "LID" => "s1",
    "EMAIL_FROM" => "#DEFAULT_EMAIL_FROM#",
    "EMAIL_TO" => "admin@site.ru",
    "SUBJECT" => "Заказ №#ORDER_ID# подтверждён",
    "BODY_TYPE" => "text",
    "MESSAGE" => "Подробности: #ORDER_DETAILS#"
);
CEventMessage::Add($arFields);

// Отправка при наступлении события
$arEventFields = array("ORDER_ID" => 123, "ORDER_DETAILS" => "...");
CEvent::Send("MY_ORDER_CONFIRMED", "s1", $arEventFields);

Bitrix24 php (bitrix24 php)

Цель - создание кастомных уведомлений без правки ядра. Используется для подтверждения заказов, регистрации, запросов обратного звонка. Почтовое событие регистрируется через CEventType::Add, затем добавляется шаблон письма. Отправка выполняется методом CEvent::Send.

  • Событие не появляется в списке административного интерфейса, если не вызвать CAgent::AddAgent для агента кеширования - принудительно обновите кеш почтовых шаблонов.
  • Письма не отправляются при отсутствии активного почтового события - проверьте флаг ACTIVE.

Как перехватить событие добавления заказа в интернет-магазине?


// Регистрируем обработчик в init.php
AddEventHandler("sale", "OnOrderAdd", array("MySaleHandler", "onOrderAdd"));

class MySaleHandler {
    public static function onOrderAdd($orderId, &$arErrors, $arData) {
        // $orderId - ID нового заказа
        // $arErrors - массив ошибок (можно добавить свою)
        // $arData - данные заказа
        $arErrors[] = "Пользователь заблокирован для заказов";
        // Вернуть false, чтобы отменить добавление
        return false;
    }
}

Bitrix php modules (модули bitrix на php)

Событие OnOrderAdd вызывается перед сохранением заказа. Возврат false отменяет создание. Используется для проверки лимитов, блокировок по IP, логирования. Важно - не выводить ошибки напрямую, а добавлять их в массив $arErrors.

  • Передача массивов по ссылке обязательна - без &$arErrors ошибки не будут зафиксированы.
  • Не следует вызывать внутри обработчика функции, которые могут инициировать то же событие (например, повторное CSaleOrder::Add), чтобы избежать рекурсии.

Как создать собственное событие для оповещения других модулей?


// Вызов пользовательского события
$event = new \Bitrix\Main\Event("mymodule", "OnBeforeAction", array("param1" => "value"));
$event->send();

// Подписка на это событие в другом модуле
$eventHandler = \Bitrix\Main\EventManager::getInstance();
$eventHandler->registerEventHandler("mymodule", "OnBeforeAction", "mymodule", "\MyClass\MyHandler", "handleEvent");

// Обработчик
class MyClass\MyHandler {
    public static function handleEvent(\Bitrix\Main\Event $event) {
        $parameters = $event->getParameters();
        // Логика обработки
    }
}

Создание собственных событий возможно через класс \Bitrix\Main\Event. Событие должно принадлежать модулю (первый аргумент). Это удобно для модульных систем, когда один модуль предоставляет точки расширения для других. Регистрация обработчиков выполняется через EventManager. Обработчик получает объект события, из которого извлекаются параметры.

  • Если обработчик не вызывается, проверьте правильность имени модуля и метода в registerEventHandler.
  • Для использования в init.php необходимо подключить \Bitrix\Main\Loader::includeModule("mymodule") перед вызовом send().
  • Не забывайте регистрировать событие в install/step.php или в административной части модуля, если модуль распространяется.

Расширенные примеры, выходящие за рамки типовых сценариев, помогут глубже понять возможности событийной модели 1С-Битрикс.

Пример

// Пример 1. Обработчик, отправляющий уведомление в Telegram при добавлении элемента
AddEventHandler("iblock", "OnAfterIBlockElementAdd", function(&$arFields) {
    $message = "Новый элемент инфоблока ".$arFields["IBLOCK_ID"].": ".$arFields["NAME"];
    $telegramToken = "ваш_токен";
    $chatId = "ваш_chat_id";
    $url = "https://api.telegram.org/bot{$telegramToken}/sendMessage?chat_id={$chatId}&text=".urlencode($message);
    file_get_contents($url);
});
// Результат: при каждом добавлении элемента в инфоблок бот присылает сообщение в чат.
// При ошибке (неверный токен) скрипт не упадёт, но сообщение не отправится.
Пример

// Пример 2. Обработчик события с использованием агента для отложенной обработки
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "scheduleHeavyTask");

function scheduleHeavyTask(&$arFields) {
    $elementId = $arFields["ID"];
    // Создаём агент, который выполнит задачу через 5 минут
    \CAgent::AddAgent(
        "heavyProcessing(".intval($elementId).");",
        "iblock",
        "N",
        300
    );
    return true;
}

function heavyProcessing($elementId) {
    // Тяжёлая обработка (генерация отчёта, интеграция со сторонним API)
    $element = \CIBlockElement::GetByID($elementId)->GetNext();
    if ($element) {
        // ... логика ...
    }
}
// Агент будет выполняться каждые 5 минут (если не удалён) до тех пор,
// пока функция не вернёт пустую строку, после чего агент удаляется.
// Важно: функция должна быть объявлена как public static или обычная функция.
Пример

// Пример 3. Передача дополнительных параметров через Closure и use
AddEventHandler("main", "OnBeforeUserAdd", function(&$arFields) use ($someExternalConfig) {
    $arFields["UF_EXTERNAL_ID"] = $someExternalConfig["prefix"].$arFields["LOGIN"];
});
// Closure позволяет передать в обработчик внешние переменные, что удобно для динамической конфигурации.
// С PHP 5.3+ такой подход допустим, но в init.php лучше избегать замыканий, если не уверены в версии PHP.
Пример

// Пример 4. Отмена события через возврат false и добавление ошибки
AddEventHandler("sale", "OnBeforeOrderAdd", function(&$arFields, &$arErrors) {
    if (checkUserLimit()) {
        $arErrors[] = "Превышен лимит заказов на сегодня";
        return false;
    }
});
// Обработчик проверяет условие и, при его выполнении, блокирует создание заказа.
// Если функция возвращает false, событие считается отменённым. 
// Ошибка будет показана пользователю на странице оформления заказа.
Пример

// Пример 5. Подписка на событие с помощью EventManager в модуле
\Bitrix\Main\EventManager::getInstance()->registerEventHandlerCompatible(
    "crm",
    "OnAfterCrmLeadAdd",
    "my.module",
    "\MyModule\LeadHandler",
    "onLeadAdded"
);

class MyModule\LeadHandler {
    public static function onLeadAdded(\Bitrix\Main\Event $event) {
        $leadId = $event->getParameter("FIELDS")["ID"];
        // Дальнейшая логика (отправка внешнему API)
    }
}
// В коробочной версии Битрикса для CRM событий лучше использовать registerEventHandlerCompatible,
// так как оно гарантирует совместимость с разными версиями модуля crm.

PHP в 1С-Битрикс - comments

En
битрикс php (php)