Разработка кастомных обработчиков событий ORM 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка кастомных обработчиков событий ORM 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка кастомных обработчиков событий ORM 1С-Битрикс

ORM D7 — это не просто обёртка над SQL. Это полноценный слой объектов с собственной событийной моделью, которая работает иначе, чем «старые» события ядра. Если OnAfterIBlockElementUpdate срабатывает при любом обновлении элемента инфоблока через любой API, то события ORM привязаны к конкретной сущности и операции с ней через DataManager. Это даёт точечный контроль: перехватить добавление записи в таблицу b_sale_order_props_value без написания триггеров в БД.

Как устроены события ORM

Каждый DataManager-класс генерирует события в четырёх точках жизненного цикла записи:

  • OnBeforeAdd — до вставки, можно модифицировать поля или отменить операцию
  • OnAfterAdd — после успешной вставки, поле ID уже доступно
  • OnBeforeUpdate — до UPDATE, можно изменить передаваемые поля
  • OnAfterUpdate — после успешного UPDATE
  • OnBeforeDelete — до DELETE, можно отменить удаление
  • OnAfterDelete — после DELETE

Событие формируется по шаблону: {ClassName}::On{Action}. Для класса Bitrix\Sale\Internals\OrderTable событие перед добавлением будет Bitrix\Sale\Internals\OrderTable::OnBeforeAdd.

Регистрация:

use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandler(
    'sale',
    '\Bitrix\Sale\Internals\OrderTable::OnAfterAdd',
    [\MyProject\Handlers\OrderOrmHandler::class, 'onAfterAdd']
);

Объект события и доступные данные

В обработчик передаётся объект \Bitrix\Main\Entity\Event. Из него извлекаются параметры:

public static function onAfterAdd(\Bitrix\Main\Entity\Event $event): void
{
    $result = $event->getParameter('result');   // объект Result с ID
    $fields = $event->getParameter('fields');   // массив сохранённых полей

    $newId = $result->getId();
    $userId = $fields['USER_ID'] ?? null;
}

Для Before-событий — можно модифицировать поля через объект Result:

public static function onBeforeAdd(\Bitrix\Main\Entity\Event $event): \Bitrix\Main\Entity\EventResult
{
    $result = new \Bitrix\Main\Entity\EventResult();

    // Добавляем/изменяем поле перед сохранением
    $result->modifyFields(['CREATED_BY' => \CUser::GetID()]);

    // Или прерываем операцию
    // $result->addError(new \Bitrix\Main\Error('Запрещено'));

    return $result;
}

Практические сценарии

Аудит изменений. Логируем, кто и когда изменил запись в кастомной HL-таблице:

public static function onAfterUpdate(\Bitrix\Main\Entity\Event $event): void
{
    $id = $event->getParameter('id')['ID'];
    $fields = $event->getParameter('fields');

    \MyProject\AuditLog::write([
        'entity'    => 'MyHlTable',
        'entity_id' => $id,
        'user_id'   => \CUser::GetID(),
        'changes'   => json_encode($fields),
        'timestamp' => new \Bitrix\Main\Type\DateTime(),
    ]);
}

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

public static function onBeforeAdd(\Bitrix\Main\Entity\Event $event): \Bitrix\Main\Entity\EventResult
{
    $result = new \Bitrix\Main\Entity\EventResult();
    $result->modifyFields([
        'CREATED_AT' => new \Bitrix\Main\Type\DateTime(),
        'STATUS'     => 'DRAFT',
        'HASH'       => md5(uniqid('', true)),
    ]);
    return $result;
}

Каскадное удаление. Перед удалением основной записи чистим связанные данные (которые ORM не удаляет автоматически без явно заданных связей):

public static function onBeforeDelete(\Bitrix\Main\Entity\Event $event): void
{
    $id = $event->getParameter('id')['ID'];
    // удаляем связанные записи через их DataManager
    \MyProject\RelatedItemTable::deleteByParentId($id);
}

Разница между ORM-событиями и «старыми» событиями

Параметр ORM-события (D7) Старые события (CMain)
Привязка Конкретный DataManager-класс Любой код, вызывающий API
Объект события \Bitrix\Main\Entity\Event Массив $arParams
Модификация полей Через EventResult::modifyFields() Через изменение переданного массива по ссылке
Отмена операции EventResult::addError() Возврат false или специфично для события
Читаемость регистрации Имя класса + операция Строка-идентификатор события

Важный нюанс: если запись создаётся через прямой SQL (Application::getConnection()->query(...)) или через старый API (CIBlockElement::Add()), ORM-события не срабатывают. ORM-события работают только при вызовах через DataManager::add(), ::update(), ::delete().

Highload-блоки и ORM-события

Для HL-блоков класс DataManager генерируется динамически. Найти имя класса:

$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById($hlId)->fetch();
$entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock);
$className = $entity->getDataClass(); // что-то вроде HlbomOrderStatusTable

Затем регистрируем обработчик на этот класс. Если нужно работать с несколькими HL-блоками — удобно создать универсальный обработчик, который маршрутизирует по имени класса.

Сроки

Задача Срок
2–4 обработчика для одной ORM-сущности (аудит, автозаполнение, валидация) 2–4 дня
Система аудита для 5–10 ORM-таблиц с хранением истории изменений 1–1.5 недели
Миграция «старых» обработчиков на ORM-события с тестированием 1–2 недели

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