OnBefore* — семейство событий, которые ядро 1С-Битрикс рассылает до выполнения операции. Именно они позволяют проверить данные и при необходимости отменить действие. Чтобы понять, как это работает, нужно разобраться с пулом событий — очередью зарегистрированных обработчиков.
Что такое пул событий
Пул событий — это внутренний реестр Битрикс, где хранятся все зарегистрированные обработчики, сгруппированные по модулю-источнику и имени события. Когда ядро доходит до точки события, оно берёт из пула список обработчиков и вызывает их по порядку сортировки.
В старом API рассылку выполняет ExecuteModuleEventEx(), в D7 — метод $event->send() объекта \Bitrix\Main\Event. Пул наполняется при регистрации обработчиков: временно (из init.php) или постоянно (из таблицы b_module_to_module).
Семантика OnBefore*
События OnBefore* вызываются перед изменением данных, и обработчику передаётся массив полей по ссылке. Это даёт две возможности:
- Изменить данные — модифицировать
$arFieldsдо сохранения (нормализовать телефон, проставить свойство, пересчитать поле); - Отменить операцию — вернуть
falseи установить текст ошибки.
Примеры таких событий: OnBeforeIBlockElementAdd, OnBeforeIBlockElementUpdate, OnBeforeUserAdd, OnSaleBeforeOrderDelete. Общее правило именования: приставка OnBefore перед именем действия.
Отмена действия и текст ошибки
В старом API отмена делается так: обработчик вызывает $APPLICATION->throwException() с текстом ошибки и возвращает false.
function onBeforeAdd(&$arFields) {
if (mb_strlen($arFields['NAME']) < 3) {
global $APPLICATION;
$APPLICATION->throwException('Название слишком короткое');
return false;
}
return true;
}
После этого метод CIBlockElement::Add() вернёт false, а текст ошибки будет доступен через $el->LAST_ERROR или $APPLICATION->GetException(). В админке ошибка покажется пользователю.
EventResult в D7
В ядре D7 обработчик не возвращает false, а формирует объект результата. Тип результата — EventResult::SUCCESS или EventResult::ERROR.
use Bitrix\Main\EventResult;
use Bitrix\Main\Event;
public static function onBefore(Event $event) {
$item = $event->getParameter('ENTITY');
if (!$item->isValid()) {
return new EventResult(
EventResult::ERROR, null, 'my.module'
);
}
return new EventResult(EventResult::SUCCESS);
}
Инициатор события проверяет результаты через $event->getResults() и, найдя ERROR, прерывает операцию. Так работают, например, события ORM модуля main.
OnBefore против OnAfter
Понимание разницы определяет, куда вешать логику.
| Признак | OnBefore* | OnAfter* / On*Add |
|---|---|---|
| Момент | До операции | После операции |
| Можно изменить данные | Да, по ссылке | Нет (уже сохранено) |
| Можно отменить | Да | Нет |
| Типичное применение | Валидация, нормализация | Интеграции, логи, уведомления |
Практические нюансы
- В
OnBefore*не все поля могут быть в$arFields: при обновлении приходят только изменяемые поля. Недостающие догружайте выборкой по ID. - Изменение
$arFieldsпо ссылке работает не для всех событий — проверяйте документацию конкретного события. - Отмена в
OnBefore*должна давать понятный текст ошибки, иначе пользователь увидит пустое сообщение. - Если операция вызвана из кода (а не из админки), проверяйте возвращаемое значение метода Add/Update — иначе отмена останется незамеченной.
Итог
Пул событий и семейство OnBefore* — основной инструмент валидации и управления операциями в 1С-Битрикс. Они дают перехватить действие до его выполнения, поправить данные или корректно отменить с понятной ошибкой. Тяжёлую же логику и интеграции держат в OnAfter*, чтобы не блокировать сохранение.
Мы проектируем валидацию и бизнес-правила на событиях так, чтобы они были предсказуемы и не мешали работе магазина. Если нужна сложная логика обработки заказов, товаров или пользователей — поможем реализовать её надёжно.
Частые вопросы
Как отменить операцию из обработчика OnBefore*?
В старом API вызвать $APPLICATION->throwException с текстом ошибки и вернуть false. В D7 вернуть EventResult с типом ERROR.
Почему изменения $arFields в обработчике не применяются?
Либо аргумент принят не по ссылке (нужно &$arFields), либо конкретное событие не поддерживает изменение данных. Проверьте сигнатуру и документацию события.
Можно ли отменить действие в OnAfter*?
Нет. OnAfter* вызывается после выполнения операции, отменить её уже нельзя. Для отмены используйте OnBefore*.
Что такое пул событий?
Это внутренний реестр зарегистрированных обработчиков, сгруппированных по модулю и имени события. Ядро берёт из него список обработчиков и вызывает их при наступлении события.
Где взять текст ошибки после отмены?
После неудачного Add/Update текст доступен через свойство LAST_ERROR объекта или через $APPLICATION->GetException()->GetString().
Почему при обновлении в $arFields не все поля?
В событиях OnBefore*Update приходят только изменяемые поля. Недостающие значения нужно догрузить выборкой по ID элемента.
Стоит ли делать запрос к внешнему API в OnBefore*?
Нет. Если внешний вызов зависнет, он заблокирует сохранение. Интеграции и внешние запросы выносите в события OnAfter*.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.