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

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка кастомних обробників подій ORM 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • 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
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка кастомних обробників подій 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-подій дають гранульний контроль над життєвим циклом даних без триггерів у БД і без перехоплення широких подій ядра. Правильно організовані обробники — це аудит, валідація і бізнес-логіка, які живуть поруч з даними, а не розкидані по всьому проекту.