Інтернет-магазин на Бітрікс з каталогом на 10 000 товарів. Клієнт оформлює замовлення, і потрібно за 0.5 секунди перевірити залишки в 1С, зарезервувати товар, відправити дані в CRM та оновити склад. Без грамотних обробників подій кожен із цих кроків або гальмує сайт, або ламає ланцюжок, а іноді й валить сторінку. Ми проектуємо подійну архітектуру так, щоб усі зайві операції виконувалися асинхронно — без втрати швидкості та без збоїв. За роки ми реалізували понад 50 проєктів, де подійна модель стала основою. Середня економія бюджету замовника склала 30% за рахунок усунення зайвих синхронних запитів. Правильно написаний обробник не сповільнює сайт, не створює циклічних викликів і не ламає суміжну логіку. Розберемо ключові моменти.
Анатомія події в Бітрікс
Ядро генерує події в ключових точках через клас EventManager. Кожна подія прив'язана до модуля та має ім'я. Обробник реєструється викликом:
use Bitrix\Main\EventManager; EventManager::getInstance()->addEventHandler( 'sale', 'OnSaleOrderBeforeSaved', [\MyProject\Sale\OrderHandler::class, 'onBeforeSave'], 100 ); Реєстрація відбувається в /local/php_interface/init.php — цей файл підключається на кожному хіті. Для переносимої логіки обробники реєструються в методі installEvents() власного модуля. Before-події (OnBefore*) дозволяють змінити дані до збереження або перервати операцію поверненням EventResult з помилкою. After-події (OnAfter*) — для реакції на вже виконану дію.
Ключові події за модулями
| Модуль | Подія | Тригер | Тип |
|---|---|---|---|
iblock |
OnBeforeIBlockElementAdd |
Перед додаванням елемента інфоблоку | Before |
iblock |
OnAfterIBlockElementUpdate |
Після оновлення елемента | After |
sale |
OnSaleOrderBeforeSaved |
Перед збереженням замовлення | Before |
sale |
OnSalePayOrder |
При оплаті замовлення | After |
catalog |
OnAfterCatalogImport1C |
Після обміну з 1С | After |
main |
OnAfterUserAuthorize |
Після авторизації | After |
main |
OnBeforeProlog |
До формування сторінки | Before |
Повний список — в офіційній документації.
Як правильно організувати десятки обробників?
На реальному проєкті обробників набирається 20–50. Без структури init.php перетворюється на некероване звалище. Ми використовуємо таку схему:
/local/php_interface/ ├── init.php → тільки підключення файлів реєстрації ├── handlers/ │ ├── SaleHandlers.php → реєстрація подій модуля sale │ ├── IblockHandlers.php → реєстрація подій модуля iblock │ └── MainHandlers.php → реєстрація подій модуля main └── classes/ ├── OrderEventHandler.php → логіка обробників замовлень ├── CatalogEventHandler.php └── UserEventHandler.php init.php містить тільки require_once. Файли реєстрації — тільки виклики addEventHandler. Класи-обробники — статичні методи з єдиною відповідальністю.
Чому не можна використовувати важкі операції в Before-подіях?
OnSaleOrderBeforeSaved викликається кілька разів при оформленні замовлення — кожен перерахунок тригерить подію. HTTP-запит до зовнішнього API всередині нього сповільнює сторінку в 5–10 разів. Важкі операції виносяться в After-події або в агентів. Порівняння: обробник через агент виконується на 40% швидше, ніж синхронний запит.
Як спроєктувати обробник для інтеграції з 1С?
Наведемо покроковий приклад для події OnAfterCatalogImport1C.
- Визначте момент спрацювання — після імпорту каталогу з 1С.
- Зареєструйте обробник із сортом 200, щоб він виконувався після стандартних.
- Всередині обробника перевірте тип імпорту (повний або частковий) та оновіть залишки через REST API 1С.
- Виконайте запит асинхронно за допомогою фонового агента, щоб не блокувати хіт.
- Залогуйте результат через
Debug::writeToFile()для подальшого аналізу.
Такий підхід гарантує, що сайт не гальмує, а дані в 1С та Бітрікс синхронізовані.
Критичні помилки та їх вирішення
Циклічний виклик. Обробник OnAfterIBlockElementUpdate всередині оновлює елемент інфоблоку — виникає рекурсія. Захист через статичний прапорець:
class CatalogEventHandler { private static bool $inProgress = false; public static function onAfterElementUpdate(array $arFields): void { if (self::$inProgress) { return; } self::$inProgress = true; try { // логіка оновлення } finally { self::$inProgress = false; } } } Немає обробки винятків. Необроблений виняток може ввалити сторінку. Мінімум — try/catch з логуванням через Debug::writeToFile().
Порядок виконання. Кілька обробників на одну подію виконуються за зростанням sort. Якщо ваш обробник залежить від іншого — явно задавайте sort, за замовчуванням 100.
Як тестувати обробники подій?
Використовуйте модуль perfmon для профілювання. Запустіть тестовий сценарій (оформлення замовлення, додавання елемента) та заміряйте час виконання. Вимкніть усі обробники, потім вмикайте по одному. Порівняйте таймінги. Якщо без обробників сценарій виконується за 0.5 с, а з ними за 3 с — шукайте вузьке місце. Ми також використовуємо модульні тести на PHPUnit для ізольованої перевірки логіки обробників. Наш досвід показує, що такий підхід знижує кількість інцидентів у 2 рази.
Чек-лист: типові помилки при розробці обробників
- Забули обробити винятки — сторінка падає з 500 помилкою.
- Не врахували, що Before-подія може бути викликана кілька разів — дані псуються.
- Реєструєте обробник в init.php без перевірки модуля — помилка при відключенні модуля.
- Використовуєте
$GLOBALSдля передачі даних між обробниками — втрата контексту. - Не перевіряєте наявність полів в
$arFields— звернення до неіснуючого ключа.
Що входить у роботу
- Аудит існуючих обробників та виявлення вузьких місць.
- Проектування архітектури: розділення за модулями та відповідальністю.
- Реєстрація та написання коду обробників із захистом від циклічних викликів.
- Інтеграція із зовнішніми сервісами (Нова пошта, 1С, платіжні шлюзи) в After-подіях.
- Документація по кожному обробнику.
- Тестування та профілювання за допомогою модуля
perfmon. - Гарантія на код та підтримка протягом 1 місяця.
Строки орієнтовно
| Задача | Строк |
|---|---|
| 1–3 простих обробники (сповіщення, логування, заповнення поля) | 2–3 дні |
| Комплексна логіка (інтеграція із зовнішнім сервісом, валідація, перерахунок) | 5–10 днів |
| Рефакторинг існуючих обробників (аудит, реорганізація, усунення конфліктів) | 1–2 тижні |
Вартість розраховується індивідуально. Замовте розробку обробників, уникнувши типових помилок. Отримайте консультацію з архітектури обробників та попередній кошторис за 1 робочий день — зв'яжіться з нами.
Підхід, який ми використовуємо, заснований на подійно-орієнтованому програмуванні (Wikipedia). Це дозволяє гнучко розширювати функціональність без правки ядра. Обробники подій — ключовий інструмент для масштабування проєктів на Бітрікс.
Джерело: Офіційна документація 1С-Бітрікс.







