Как использовать OnBeforeIBlockElementUpdate в 1С-Битрикс без затирания свойств?

Как использовать OnBeforeIBlockElementUpdate в 1С-Битрикс без затирания свойств?

Контент-менеджер сохранил в списке только новое название товара, а характеристики исчезли. Типичная ошибка на практике: вчера в init.php повесили OnBeforeIBlockElementUpdate, в обработчике поправили свойство без isset — свойства пропали, умный фильтр не работает. Главная проблема не в Update, а в отсутствии isset: ядро восприняло это как полную перезапись PROPERTY_VALUES. Ниже — как использовать AddEventHandler в init.php, безопасно работать с &$arFields, отменить Update через ThrowException и return false, и получить предсказуемый результат при частичном сохранении.

OnBeforeIBlockElementUpdate - событие модуля iblock, вызываемое внутри CIBlockElement::Update до записи в БД. Обработчик получает &$arFields по ссылке: правки полей применяются, а отмена Update - через $APPLICATION->ThrowException() и return false. Критично: трогать PROPERTY_VALUES только если ключ передан в вызове Update, иначе свойства элемента будут очищены. Сегодня: повесьте обработчик в init.php, оберните свойства в isset, для одного свойства смотрите SetPropertyValuesEx в гайде по Update.

Речь про 1С-Битрикс: Управление сайтом, не про Bitrix24. Событие срабатывает при любом CIBlockElement::Update: админка, импорт, cron. Семантику Update и PROPERTY_VALUES разбираем в гайде по CIBlockElement::Update. Общую схему init.php и AddEventHandler - в статье про обработчики событий.

Что такое OnBeforeIBlockElementUpdate и когда он нужен

Сравнение OnBeforeIBlockElementUpdate и OnAfter: когда срабатывает событие и что можно менять в &$arFields

OnBeforeIBlockElementUpdate - проверка перед записью элемента инфоблока в базу. Представьте фильтр на входе: пока массив $arFields не прошел вашу логику, CIBlockElement::Update не запишет изменения. Обработчик может подправить поля или запретить сохранение целиком.

Нужен, когда при любом Update надо валидировать поля, нормализовать CODE, запретить пустой DETAIL_TEXT у активных товаров или проверить связку свойств каталога. Не нужен, если из cron меняете одно свойство - точечнее SetPropertyValuesEx (B40). Не путайте с общим AddEventHandler для sale или main: здесь модуль iblock, событие OnBeforeIBlockElementUpdate, сигнатура (&$arFields).

Зарегистрируйте обработчик в init.php через AddEventHandler

Схема регистрации OnBeforeIBlockElementUpdate через AddEventHandler в init.php Битрикс
  1. Откройте /bitrix/php_interface/init.php на тестовой копии.
  2. Добавьте AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'MyOnBeforeElementUpdate').
  3. Объявите функцию с (&$arFields) - без ссылки правки не применятся.
  4. Отфильтруйте IBLOCK_ID в первых строках обработчика и проверьте сохранение в админке.
<?php
AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'MyOnBeforeElementUpdate');

function MyOnBeforeElementUpdate(&$arFields)
{
    if ((int)$arFields['IBLOCK_ID'] !== 7) {
        return true;
    }
    return true;
}

В модуле (D7): EventManager::getInstance()->addEventHandler('iblock', 'OnBeforeIBlockElementUpdate', ['\\Vendor\\Handlers', 'onBeforeUpdate']). Для addeventhandler bitrix в init.php хватает старого ядра. Сделайте: фильтр по инфоблоку сразу. Не делайте: копировать гист без понимания охвата.

Отмените Update через ThrowException и return false

Чеклист отмены Update элемента инфоблока через ThrowException и return false в Битрикс

Невалидные данные останавливают сохранение так: $APPLICATION->ThrowException('текст'), затем return false. Без return false Update может пройти.

function MyOnBeforeElementUpdate(&$arFields)
{
    if (empty(trim($arFields['NAME']))) {
        global $APPLICATION;
        $APPLICATION->ThrowException('Название не может быть пустым.');
        return false;
    }
    return true;
}

В админке редактор увидит текст ошибки. В скрипте — $el->LAST_ERROR. Сделайте: понятные сообщения на русском. Не делайте: отменять импорт без явной причины.

Обойдите ловушку PROPERTY_VALUES: проверяйте isset

Типичная ошибка на практике после копипаста гайда в прод: в реальном проекте разработчик повесил AddEventHandler, в обработчике написал $arFields['PROPERTY_VALUES'][$propId] = 'нормализованное значение'. Контент-менеджер сохранил элемент из списка только с новым NAME. Вызов Update не передал PROPERTY_VALUES, но обработчик создал ключ — ядро восприняло это как полную перезапись и очистило артикулы, бренды, фото-привязки.

Цепочка: частичный Update без свойств → обработчик без isset → wipe. Та же семантика, что при неполном ciblockelement update в скрипте импорта - подробно в B40. Комментарий Д. Турчина в официальной справке OnBefore прямо предупреждает про isset перед PROPERTY_VALUES.

if (isset($arFields['PROPERTY_VALUES'])) {
    $arFields['PROPERTY_VALUES'][42] = trim($arFields['PROPERTY_VALUES'][42]);
}

Без isset($arFields['PROPERTY_VALUES']) свойства не трогайте. Для одного свойства из cron используйте SetPropertyValuesEx (ciblockelement setpropertyvalues), не OnBefore. Сделайте: isset перед любой записью. Не делайте: «нормализовать артикул», если Update без свойств.

Проверяйте isset для DETAIL_TEXT при частичном Update

В $arFields только то, что передал вызов Update. Из списка может не быть DETAIL_TEXT, PREVIEW_TEXT, SHOW_COUNTER. str_replace без isset обнуляет текст при смене раздела.

if (isset($arFields['DETAIL_TEXT']) && $arFields['DETAIL_TEXT'] !== '') {
    $arFields['DETAIL_TEXT'] = str_replace('old.domain', 'new.domain', $arFields['DETAIL_TEXT']);
}

Для сравнения с базой — CIBlockElement::GetByID, не ждите полный снимок в событии. Сделайте: isset на каждое поле. Не делайте: полагаться на «все поля элемента» при bitrix update element property из админки.

Сравните OnBefore и OnAfterIBlockElementUpdate

Разработчики часто переносят код из OnBefore в OnAfter и удивляются, что "ничего не сохранилось". В OnAfterIBlockElementUpdate &$arFields по ссылке, но официальная справка прямо говорит: манипуляции с массивом не изменят данные в БД. OnAfter срабатывает даже при неудачном Update, поэтому всегда проверяйте $arFields['RESULT'] и $arFields['RESULT_MESSAGE'].

Схема событий Update:
OnStartIBlockElementUpdate → OnBeforeIBlockElementUpdate (правки, отмена) → запись в БД → OnAfterIBlockElementUpdate (лог, очередь при RESULT=true)
Критерий OnBeforeIBlockElementUpdate OnAfterIBlockElementUpdate
Момент До записи в БД После попытки Update
Правка &$arFields Применяется Не меняет БД
Отмена ThrowException + return false Невозможна
Успех return false RESULT === true
Итог: валидацию и правки полей - в OnBefore. OnAfter - лог и побочные действия при успешном RESULT. CCatalogProduct::Update в OnAfter часто не сохраняется - для цен ищите события catalog или OnBefore.

Прогоните чек-лист перед деплоем

  1. Бэкап базы и init.php.
  2. Тест на копии: карточка, список, импорт - свойства на месте.
  3. Журнал событий iblock без fatal error.
  4. Откат: removeEventHandler или комментарий регистрации.

На staging снимите обработчик через removeEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'MyOnBeforeElementUpdate') - ядро править не нужно. Если свойства пропали на проде - первым делом isset($arFields['PROPERTY_VALUES']) и контракт Update в B40. Нужен аудит цепочки событий и импорта на боевом проекте - напишите через контакты, разберем onbeforeiblockelementupdate и соседние обработчики.

Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: OnBeforeIBlockElementUpdate, OnAfterIBlockElementUpdate, CIBlockElement::Update.

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

Почему после Update пропали свойства из-за обработчика?

Update без PROPERTY_VALUES, а обработчик OnBeforeIBlockElementUpdate записал в $arFields['PROPERTY_VALUES'] без isset - ядро удалило остальные свойства. Оберните работу в isset($arFields['PROPERTY_VALUES']). Для одного свойства - SetPropertyValuesEx (B40).

Чем OnBeforeIBlockElementUpdate отличается от OnAfterIBlockElementUpdate?

OnBefore - до записи: правки &$arFields применяются, отмена через ThrowException и return false. OnAfter - после Update: &$arFields не сохраняется в элемент; только лог при RESULT === true. Валидацию не переносите в After.

Можно ли отменить обновление из обработчика?

Да, в OnBeforeIBlockElementUpdate: $APPLICATION->ThrowException('текст'); return false;. В OnAfter отменить запись нельзя.

Где регистрировать обработчик инфоблока?

В /bitrix/php_interface/init.php: AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'ИмяФункции'). Подробности init.php - B58. В модуле - EventManager::addEventHandler с модулем iblock.

Нужен ли OnBefore для одного свойства?

Обычно нет. Для "битрикс обновить свойство элемента" из cron безопаснее SetPropertyValuesEx. OnBefore - когда контролируете каждое сохранение из админки.

Почему в $arFields не все поля элемента?

В событие попадает только то, что передан в CIBlockElement::Update. Из списка может не быть DETAIL_TEXT. Проверяйте isset; для текущих значений - GetByID.

Как использовать onbeforeiblockelementupdate битрикс на staging?

Копия прода, AddEventHandler в init.php, три теста: карточка, список, импорт. Проверьте свойства. Откат - removeEventHandler. Логи - журнал событий iblock.

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

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

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

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

Как настроить скидки и промокоды на 1С-Битрикс: правила корзины и купоны

Пошаговый гайд по скидкам в CMS-магазине: скидка на товар, правило корзины от суммы, купоны с лимитом, приоритеты без конфликтов и тестовый заказ. Не Bitrix24.
Интеграции с 1С и API
757 15 мин.

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

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

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

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

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

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