Как добавить обработчик событий на 1С-Битрикс через init.php?

Как добавить обработчик событий на 1С-Битрикс через init.php?

Заказ оформился, а интеграция с CRM дернулась три раза - и в логах три одинаковые строки. Вы вставили AddEventHandler в init.php, но в поиске половина статей про облачную CRM, а не про CMS на вашем хостинге. Ниже - куда положить PHP-код, как подписаться на событие модуля sale или iblock, отличить модульное событие от почтового шаблона и добиться одного срабатывания на тестовом заказе.

Обработчик события - это PHP-функция или метод класса, которую Битрикс вызывает в нужный момент: после сохранения заказа, добавления элемента инфоблока, до отрисовки страницы. Глобальные подписки пишут в /local/php_interface/init.php через AddEventHandler или EventManager D7. Постоянные - в InstallEvents модуля через registerEventHandler. Два обработчика на одно событие дают два письма или два webhook. Для заказов проверяйте IS_NEW в OnSaleOrderSaved.

На практике типичная ошибка: скопировали обработчик из статьи про события, а в init.php уже висит подписка модуля маркетплейса - CRM уходит трижды. Например, ночной заказ уже в админке, а в логе три строки MY_ORDER_HANDLER.

Речь про CMS "1С-Битрикс: Управление сайтом" на сервере, не про Bitrix24. Модульное событие - сигнал из PHP (sale, iblock, main). Почтовый шаблон - другая цепочка: гайд B56. Если CRM дергается после каждого статуса заказа, сначала обработчики, потом обработка заказов.

Разберите, когда нужен обработчик на CMS

Сравнение: модульное событие, почтовый шаблон и облачная CRM в Битрикс

Обработчик нужен, когда стандартного поведения мало. Типичные задачи: отправить заказ во внешнюю CRM, проставить символьный код элементу инфоблока, записать метрику до вывода HTML. Это не настройка письма клиенту и не сценарий в облачной CRM.

Что настраиваете Где живет Типичный триггер
Модульное событие (PHP) init.php или модуль OnSaleOrderSaved, OnAfterIBlockElementAdd
Почтовый шаблон Админка "Почтовые события" SALE_NEW_ORDER, FEEDBACK_FORM
Облачная CRM (automation) Облако CRM Роботы, бизнес-процессы - out of scope

Триггеры: заказ (sale), элемент каталога (инфоблок), регистрация (main). Делайте: логику "после сохранения в БД" - через модульное событие. Не делайте: не путайте OnBeforeEventSend с OnSaleOrderSaved.

Выберите, где разместить код без правки ядра

Схема размещения кода: init.php в local vs InstallEvents модуля

Файл init.php подключается при каждом хите сайта. Правильный путь - /local/php_interface/init.php: он не затирается при обновлении ядра в /bitrix. Код в /bitrix/php_interface/init.php после апдейта может пропасть.

Задача Куда писать Метод регистрации
Разовая доработка на проекте /local/php_interface/init.php AddEventHandler или addEventHandler
Функция в своем модуле install/index.php, InstallEvents registerEventHandler / unRegisterEventHandler
Правка ядра /bitrix/modules/... Запрещено

В модуле подписку снимают при удалении через unRegisterEventHandler. Делайте: init.php в local. Не делайте: не регистрируйте в include.php без InstallEvents.

Зарегистрируйте обработчик через AddEventHandler и EventManager D7

Чеклист регистрации: AddEventHandler и EventManager D7 с параметром sort

AddEventHandler - классический API: модуль, событие, функция или метод. EventManager D7 - современный слой; ядро проксирует legacy в addEventHandlerCompatible. sort (по умолчанию 100) задает порядок: меньше число - раньше вызов.

Пример в init.php для инфоблока:

use Bitrix\Main\EventManager;

$eventManager = EventManager::getInstance();
$eventManager->addEventHandler(
    'iblock',
    'OnAfterIBlockElementAdd',
    ['\\Local\\Handlers\\IblockHandler', 'onAfterAdd']
);

В модуле при установке:

use Bitrix\Main\EventManager;

$em = EventManager::getInstance();
$em->registerEventHandler(
    'sale',
    'OnSaleOrderSaved',
    'vendor.mymodule',
    '\\Vendor\\Mymodule\\OrderHandler',
    'onOrderSaved'
);

При удалении - unRegisterEventHandler с теми же аргументами. Старый код с $arFields по ссылке - addEventHandlerCompatible. В D7 аргументы: $event->getParameters().

  1. Откройте или создайте /local/php_interface/init.php.
  2. Найдите имя события в справочнике событий нужного модуля.
  3. Зарегистрируйте обработчик через EventManager::addEventHandler или AddEventHandler.
  4. Вынесите логику в класс с автозагрузкой, а не в гигантскую функцию в init.php.
  5. На staging оформите тестовое действие (заказ, элемент инфоблока).
  6. Убедитесь, что обработчик вызвался ровно один раз.

Делайте: registerEventHandler для кода в модуле, addEventHandler для проектных правок. Не делайте: не регистрируйте один и тот же callback и в init.php, и в InstallEvents - получите дубль.

Настройте типовые сценарии: заказ, инфоблок, пролог

OnAfterIBlockElementAdd - после элемента каталога: автокод, синхронизация. OnSaleOrderSaved вызывается при каждом сохранении заказа - не баг. Для "только новый" проверяйте IS_NEW:

public static function onOrderSaved(\Bitrix\Main\Event $event)
{
    if ($event->getParameter('IS_NEW') !== true) {
        return;
    }
    $order = $event->getParameter('ENTITY');
    // отправка в CRM один раз
}

OnBeforeProlog - до вывода страницы; тяжелую логику лучше в агенты. Регистрация - main/OnAfterUserAdd (личный кабинет).

Делайте: для заказов фильтруйте IS_NEW или используйте OnSaleOrderBeforeSaved, если нужно изменить данные до записи. Не делайте: не вешайте тяжелый API-вызов на OnBeforeProlog без крайней необходимости.

Найдите причину двойного или тройного срабатывания

Схема диагностики: событие сработало → findEventHandlers показал N обработчиков → каждый дал side-effect → клиент получил N писем.

Алгоритм: заказ или элемент → EventManager::getInstance()->findEventHandlers('sale', 'OnSaleOrderSaved') → если записей больше одной, ищите дубль в init.php и модуле → removeEventHandler для теста → повторите сценарий.

Причины: дубль в init.php и модуле; OnSaleOrderSaved без IS_NEW при смене статусов; восстановленный init.php поверх старой подписки модуля.

Делайте: перед продом выведите список findEventHandlers на staging. Не делайте: не копируйте сниппеты с Habr в init.php, не проверив, нет ли того же в модуле маркетплейса.

Проверьте работу через журнал событий и отладку

На staging - Debug::writeToFile в /local/logs/. В проде - журнал событий (/bitrix/admin/event_log.php):

CEventLog::Add([
    'SEVERITY' => 'INFO',
    'AUDIT_TYPE_ID' => 'MY_ORDER_HANDLER',
    'MODULE_ID' => 'sale',
    'ITEM_ID' => $orderId,
    'DESCRIPTION' => 'Обработчик OnSaleOrderSaved отработал',
]);

Отключить без удаления кода: removeEventHandler с теми же параметрами.

  1. Включите запись CEventLog::Add или Debug::writeToFile в начале обработчика.
  2. Выполните тестовый сценарий на staging.
  3. Откройте журнал событий или файл лога.
  4. Сверьте число записей с ожидаемым числом вызовов.
  5. Если записей больше - запустите findEventHandlers и уберите дубли.
  6. Зафиксируйте рабочую конфигурацию в документации проекта.

Если после правок интеграция все еще ведет себя странно, напишите нам - разберем цепочку на реальном проекте.

Делайте: логируйте ITEM_ID заказа или элемента. Не делайте: не оставляйте var_dump в обработчике на бою - сломаете вывод страницы.

Пройдите чек-лист перед выкладкой на прод

Workflow перед релизом: код в /local/ или модуле, один обработчик на событие, тест на staging. Дальше - запись в журнале, снятие тестовых removeEventHandler, деплой.

  • Обработчик лежит в /local/php_interface/init.php или в InstallEvents модуля, не в /bitrix/modules.
  • findEventHandlers показывает одну запись на нужное событие.
  • Для заказов проверен IS_NEW, если нужен только первый вызов.
  • Тестовый заказ или элемент на staging дал ожидаемый результат.
  • В журнале событий есть тестовая запись с вашим AUDIT_TYPE_ID.
  • При удалении модуля вызывается unRegisterEventHandler.

Кейсы - в портфолио. Делайте: документируйте подписки. Не делайте: API на прод без таймаута.

Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: документация EventManager D7, AddEventHandler, события сохранения заказа.

Частые вопросы

Чем обработчик события отличается от почтового шаблона?

Почтовый шаблон формирует письмо по типу события (SALE_NEW_ORDER) в админке. PHP-обработчик - ваш код на модульном событии (OnSaleOrderSaved), который может отправить API-запрос, записать лог или изменить данные. Письмо клиенту и интеграция с CRM - разные задачи; шаблоны настраивают в гайде B56.

Где лежит init.php в Битрикс?

Рабочий путь - /local/php_interface/init.php в корне сайта. Если папки local нет, создайте ее по структуре документации. Файл /bitrix/php_interface/init.php не рекомендуют: при обновлении продукта правки могут потеряться.

addEventHandler или registerEventHandler - что выбрать?

addEventHandler (или AddEventHandler) - для кода в init.php на конкретном проекте. registerEventHandler - когда обработчик входит в состав модуля: подписка сохраняется в базе и снимается через unRegisterEventHandler при удалении модуля. Не дублируйте оба варианта на одно событие.

Почему обработчик срабатывает дважды или трижды?

Чаще всего зарегистрированы два обработчика на одно событие - в init.php и в модуле. Реже OnSaleOrderSaved вызывается при каждом пересохранении заказа (статус, оплата). Проверьте findEventHandlers и добавьте проверку IS_NEW для сценария "только новый заказ".

Можно ли отключить обработчик без удаления кода?

Да. Вызовите EventManager::removeEventHandler с теми же параметрами module, event, class и method, что при регистрации. Для временной отладки на staging это быстрее, чем комментировать весь блок в init.php.

Это то же самое, что события в облачной CRM?

Нет. Роботы и JS BX.addCustomEvent - другой продукт. Статья про CMS "Управление сайтом" на PHP-хостинге: AddEventHandler, init.php, модули sale и iblock. Автоматизацию облачной CRM сюда не переносят.

Читайте также

Интеграции с 1С и API
947 6 мин.

Как настроить регистрацию и личный кабинет покупателя на 1С-Битрикс?

Пошаговая настройка регистрации на сайте битрикс: Главный модуль, main.register, system.auth.form и sale.personal.section с историей заказов и 152-ФЗ.
Интеграции с 1С и API
675 15 мин.

Что такое компонент в Битриксе и как он работает

Каждый разработчик, впервые столкнувшийся с Битриксом, проходит через своеобразный обряд посвящения. Вначале кажется, что это просто CMS, где можно поправить HTML в визуальном редакторе или дописать пару строк CSS. Но однажды наступает момент, когда нужно изменить логику вывода новостей, отфильтровать товары по хитрому свойству или добавить на страницу нечто совершенно новое. И тут он впервые слышит это слово — «компонент». Для многих этот момент становится стеной. Система, казавшаяся понятной, вдруг превращается в черный ящик, полный непонятных файлов и странных переменных. Но стоит лишь раз заглянуть под капот, как эта стена рассыпается, превращаясь в набор удивительно логичных и мощных строительных блоков. Понимание компонентов — это тот самый щелчок, после которого разработка на Битрикс из мучения превращается в творчество.

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

Интеграции с 1С и API
605 2 мин.

Установка Composer в 1С-Битрикс

Установка Composer в проекте на 1С-Битрикс требует учета особенностей платформы, чтобы обеспечить корректную работу и интеграцию с системой.