Как изменить и удалить свойство инфоблока через CIBlockProperty::Update?

На практике после миграции CIBlockProperty::Update возвращает true, а в админке галочка "Показывать в умном фильтре" пустая. На следующем шаге разработчик вызвал CIBlockProperty::Delete, думая что "почистит" значения у 12 000 SKU, и снёс все данные каталога - хотел только обнулить поле через SetPropertyValuesEx. Ниже - безопасный Update (NAME, CODE, SMART_FILTER, UpdateEnum) и Delete с каскадом, LAST_ERROR и альтернативой ACTIVE=N на проде.

CIBlockProperty::Update и CIBlockProperty::Delete в 1С-Битрикс: Управление сайтом - legacy-методы класса CIBlockProperty для изменения схемы свойства инфоблока (NAME, CODE, PROPERTY_TYPE, SMART_FILTER, VALUES) и полного удаления свойства вместе со всеми значениями элементов. Update - нестатический, возвращает true/false и LAST_ERROR; Delete - статический с 3.0.3, каскадно чистит enum, section links и колонки b_iblock_element_prop_s*. Не меняют значения элементов точечно - для этого SetPropertyValuesEx. Сегодня: перед Update снимите GetList, для SMART_FILTER передавайте IBLOCK_ID в arFields, для enum - полный массив в UpdateEnum, Delete только на staging с бэкапом.

Речь про 1С-Битрикс: Управление сайтом (CMS на вашем сервере), не про облачный Bitrix24 CRM. Свойство инфоблока - "колонка" каталога: цвет, бренд, артикул. Создать новое поле - CIBlockProperty::Add (B93). Записать значение в карточку товара - CIBlockElement::Update и SetPropertyValuesEx (B40). Здесь - правка и удаление уже существующей схемы свойства.

Разберите, когда нужен Update или Delete, а не Add и не SetPropertyValuesEx

Таблица сравнения: когда CIBlockProperty::Update, Delete, Add или SetPropertyValuesEx

CIBlockProperty::Update меняет описание поля в структуре инфоблока: подпись, CODE, тип, флаги фильтра. CIBlockProperty::Delete убирает поле целиком из схемы и каскадно стирает все значения у элементов. Это другой уровень, чем правка товара.

Задача Метод Что трогает
Новое поле в каталоге CIBlockProperty::Add (B93) Схема: новая строка в b_iblock_property
Поменять NAME, SMART_FILTER, CODE CIBlockProperty::Update Схема существующего свойства по ID
Обнулить цвет у одного SKU SetPropertyValuesEx(false) Значение у элемента, схема цела
Убрать legacy-поле с 12 000 товаров Delete или ACTIVE=N Delete - схема + все значения; ACTIVE=N - только скрыть

Типичный сценарий: Sprint Migration (B65) на деплое массово включает SMART_FILTER через Update в цикле GetList. Настройка фильтра руками в админке - гайд B53.

Делайте: Update/Delete в миграциях и скрипах чистки legacy-схемы. Не делайте: Delete когда нужно только очистить значения - это SetPropertyValuesEx.

Что такое CIBlockProperty::Update и Delete

Схема workflow CIBlockProperty::Update и Delete с проверкой LAST_ERROR

Update - нестатический, при false - LAST_ERROR. Delete - статический с 3.0.3. На проде - ACTIVE=N, не Delete.

Выполните Update: GetList до/после, NAME, CODE и LAST_ERROR

Чеклист шагов CIBlockProperty::Update: GetList, NAME, CODE, LAST_ERROR
  1. Модуль: Loader::includeModule('iblock').
  2. Снимок до: GetList по ID - NAME, CODE, SMART_FILTER.
  3. Объект и вызов: $ibp = new CIBlockProperty; $ok = $ibp->Update($propId, $arFields);
  4. Ошибка и проверка: при !$ok читайте $ibp->LAST_ERROR в лог миграции; при успехе - повторный GetList, поля должны совпасть с ожиданием.
<?php
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
$iblockId = 7;
$propId = 42;
$ibp = new CIBlockProperty;
$ok = $ibp->Update($propId, [
    'IBLOCK_ID' => $iblockId,
    'NAME' => 'Цвет товара',
    'SORT' => 150,
]);
if (!$ok) {
    throw new \RuntimeException($ibp->LAST_ERROR);
}

Делайте: IBLOCK_ID в arFields при каждом Update. Не делайте: менять PROPERTY_TYPE с данными - ядро очистит значения элементов.

Устраните ловушку SMART_FILTER: IBLOCK_ID и SECTION_PROPERTY

Типичная ошибка на стейдже: Update с SMART_FILTER=Y возвращает true, но галочка в админке пустая. Например, в arFields забыли IBLOCK_ID - LAST_ERROR в этом случае тоже молчит (кейс с форума и пример 4 в Update.php).

Цепочка умного фильтра: SECTION_PROPERTY=Y у инфоблока → Update с IBLOCK_ID и SMART_FILTER=Y → CIBlockSectionPropertyLink для разделов → сброс кеша catalog.smart.filter
  1. Проверьте инфоблок: CIBlock::GetArrayByID($iblockId)['SECTION_PROPERTY'] должен быть Y.
  2. Если N: CIBlock::Update($iblockId, ['SECTION_PROPERTY' => 'Y']).
  3. Массовый паттерн (bazarow): GetList по IBLOCK_ID, в цикле Update с IBLOCK_ID, SMART_FILTER=Y, при необходимости DISPLAY_TYPE и DISPLAY_EXPANDED.
$res = CIBlockProperty::GetList(['SORT' => 'ASC'], ['IBLOCK_ID' => $iblockId]);
$ibp = new CIBlockProperty;
while ($row = $res->Fetch()) {
    $ibp->Update($row['ID'], [
        'IBLOCK_ID' => $iblockId,
        'SMART_FILTER' => 'Y',
    ]);
}

Делайте: проверьте галочки и фильтр на витрине. Не делайте: Update SMART_FILTER без IBLOCK_ID.

Настройте SECTION_PROPERTY и CIBlockSectionPropertyLink

SMART_FILTER в карточке свойства не равен фильтру в разделе - нужен CIBlockSectionPropertyLink::Add. SaveAction в админке ставит SECTION_PROPERTY=Y; legacy Update - нет. UI - гайд B53.

Правьте списки (PROPERTY_TYPE=L) через UpdateEnum без потери enum

Для списочных свойств варианты хранятся в CIBlockPropertyEnum. UpdateEnum требует полный массив arVALUES: отсутствующие ID удаляются из enum. Перед правкой снимите GetPropertyEnum и сохраните все существующие ID.

  1. До: CIBlockProperty::GetPropertyEnum($code, [], ['IBLOCK_ID' => $iblockId]).
  2. Merge: добавьте новый вариант как n0, сохраните старые как ID=>поля.
  3. Вызов: $ibp->UpdateEnum($propId, $arVALUES) или через Update с ключом VALUES при полной замене.
  4. После: снова GetPropertyEnum - ни один старый ID не должен пропасть без намерения.

Enum ID - B88. Не делайте: UpdateEnum только с новыми вариантами - старые enum удалятся.

Удалите свойство через Delete: каскад и OnBeforeIBlockPropertyDelete

Delete каскадно: enum, CIBlockSectionPropertyLink, колонки prop_s*, все значения элементов. Порядок: бэкап → ACTIVE=N на проде → Delete на staging → фасет и тест B90.

  1. OnBeforeIBlockPropertyDelete с ThrowException отменяет Delete.
  2. CIBlockProperty::Delete($propId) только после GetList на копии.

Делайте: Delete только для legacy без данных. Не делайте: Delete вместо SetPropertyValuesEx(false).

Сравните Delete, SetPropertyValuesEx, Element::Update и ACTIVE=N

Задача Метод Результат
Убрать поле из схемы и БД CIBlockProperty::Delete Свойство и все значения удалены
Очистить цвет у товара #123 SetPropertyValuesEx(['COLOR' => false]) Значение пусто, свойство COLOR есть
Скрыть legacy-поле на проде Update ACTIVE=N Не в админке, данные в БД
Поменять название товара CIBlockElement::Update Элемент, не схема свойства (B40)

Делайте: выбирайте метод по таблице перед любым скриптом чистки. Не делайте: массовый Delete в проде без ACTIVE=N и бэкапа.

Подключите события OnBeforeIBlockPropertyUpdate и миграции

OnBeforeIBlockPropertyUpdate блокирует смену CODE на проде; OnBeforeIBlockPropertyDelete - страховка от Delete. В arrilot/bitrix-migrations update() бросает LAST_ERROR; deleteIblockElementPropertyByCode() - GetList по CODE и Delete.

Проверьте чек-лист после Update и Delete на staging

Финальный контроль перед merge в main:

  1. GetList подтверждает новые NAME, CODE, SMART_FILTER или отсутствие свойства после Delete.
  2. LAST_ERROR пуст при успешном Update; при false - текст в логе миграции.
  3. Для списка L: GetPropertyEnum до/после - enum не пропали.
  4. Фасетный индекс пересоздан; умный фильтр на витрине показывает поле; тестовый элемент через CIBlockElement::Add (B90) записывается в оставшиеся свойства без ошибок.

Облачный Bitrix24 здесь не применим - только коробочная CMS. Вопросы по цепочке Add → Update → Delete - обсудим проект. Кейсы миграций каталога - в портфолио.

Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: CIBlockProperty::Update, CIBlockProperty::Delete, CIBlockProperty::UpdateEnum, OnBeforeIBlockPropertyDelete.

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

Чем CIBlockProperty::Update отличается от Add?

Add создаёт новое свойство и возвращает ID. Update меняет уже существующее по числовому ID свойства: NAME, CODE, флаги SMART_FILTER и др. Для нового поля - Add (B93); для правки схемы - Update с IBLOCK_ID в arFields.

Можно ли изменить CODE свойства через Update?

Да, CODE передаётся в arFields Update. Но на проде это ломает шаблоны, импорт и PROPERTY_VALUES по старому коду. Блокируйте смену CODE в OnBeforeIBlockPropertyUpdate или делайте миграцию данных перед Update.

Почему SMART_FILTER не сохраняется при успешном Update?

Чаще всего в arFields CIBlockProperty::Update не передан IBLOCK_ID - метод возвращает true, галочка пустая, LAST_ERROR молчит. Второй случай: SECTION_PROPERTY=N у инфоблока. Проверьте CIBlock::GetArrayByID и CIBlockSectionPropertyLink::Add для разделов.

Удаляются ли значения элементов при CIBlockProperty::Delete?

Да, Delete каскадно удаляет все значения этого свойства у всех элементов инфоблока, enum-варианты, связи с разделами и колонки в prop_s. Для очистки одного товара используйте SetPropertyValuesEx с false, не Delete.

Когда использовать UpdateEnum, а не VALUES в Update?

UpdateEnum - для точечной правки списка PROPERTY_TYPE=L: добавить вариант, сохранить старые ID. VALUES в Update - при создании свойства или полной замене списка. Перед UpdateEnum снимите GetPropertyEnum и передавайте полный массив - подробнее в B88.

Когда Delete опасен на проде?

При любом свойстве с живыми данными каталога. Порядок: бэкап, staging с копией, ACTIVE=N на проде, проверка фасета и фильтра, Delete только если поле точно не нужно. OnBeforeIBlockPropertyDelete может отменить удаление через ThrowException.

Обсудить вашу задачу

Было полезно?

Поставьте лайк, если статья помогла разобраться.

Поделиться статьёй

Отправьте тому, кому это пригодится.

Telegram ↗ MAX ↗ ВКонтакте ↗ Одноклассники ↗
Все статьи ↗

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

Структура шаблонов сайта в Битриксе и поиск header footer

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