Ночной обмен с 1С пишет в лог "обновлено 4000 SKU", а утром в каталоге пустые артикулы, фото и привязки. Разработчик добавил в CIBlockElement::Update три свойства из семи - и остальные исчезли. Это не "баг ядра", а контракт PROPERTY_VALUES: если ключ есть в массиве, Битрикс ждет полный набор свойств. Ниже - decision tree (Update, SetPropertyValues, SetPropertyValuesEx, D7 ORM), безопасные сниппеты для ciblockelement update и чек-лист, если свойства слетают без вашего ведома.
CIBlockElement::Update в 1С-Битрикс: Управление сайтом - метод класса CIBlockElement для программного изменения полей элемента инфоблока (NAME, ACTIVE, картинки, разделы). Если в массив $arFields передан ключ PROPERTY_VALUES, ядро ожидает полный набор значений свойств; неуказанные свойства удаляются (кроме типа "файл"). Для точечного обновления без затирания - SetPropertyValuesEx или SetPropertyValues с четвертым параметром $PROPERTY_CODE. Сегодня: поля - Update без PROPERTY_VALUES, одно свойство - SetPropertyValuesEx, при false читайте $el->LAST_ERROR.
Речь про 1С-Битрикс: Управление сайтом, не про Bitrix24. Элемент инфоблока - товар, новость, услуга. Инфоблок еще не создан - гайд по созданию инфоблока. Создание элемента с нуля - CIBlockElement::Add. Массовый импорт - интеграция 1С с сайтом. Сборку каталога и карточек сверьте в гайде по интернет-магазину на Bitrix.
Что такое CIBlockElement::Update и когда он нужен
CIBlockElement::Update - PHP-метод для изменения элемента по ID: название, активность, картинки, разделы. Свойства трогает только при ключе PROPERTY_VALUES в $arFields. Нужен в коде при массовых правках (cron, 1С). Перед ночным импортом сделайте резервные копии Битрикс — при затирании свойств откатите через restore.php. После правок на витрине не видно изменений — очистите кэш битрикс, включая resize cache. Не нужен для одной карточки - админка безопаснее. Пара к CIBlockElement::Add: при создании пустой PROPERTY_VALUES допустим.
Разберите, когда нужен Update в коде, а не правка в админке
| Ситуация | Админка | Update / SetPropertyValuesEx |
|---|---|---|
| Одна правка | Быстрее | Избыточно |
| Импорт 5000 SKU | Нереально | Обязателен API |
| Скрыть без остатка | Долго | Update ACTIVE без PROPERTY_VALUES |
| Только цена | Риск ошибки | SetPropertyValuesEx |
Делайте: автоматизируйте массовые правки. Не делайте: Update для разовых правок в админке.
Подготовьте скрипт: модуль iblock, ID и снимок свойств
- Модуль:
Loader::includeModule('iblock'). - ID: ELEMENT_ID и IBLOCK_ID из админки или GetList.
- Коды свойств: PRICE, ARTICLE - как в настройке свойств каталога; здесь — только запись значений через API.
- Снимок: GetProperty "до";
$el = new CIBlockElement;для Update и LAST_ERROR.
Loader::includeModule('iblock');
$el = new CIBlockElement;
$rs = CIBlockElement::GetProperty($iblockId, $elementId);
Делайте: тест на одном ID. Не делайте: импорт без снимка GetProperty.
Выберите метод: Update, SetPropertyValues, SetPropertyValuesEx или D7 ORM
Типичная ошибка при bitrix update element property - смешать пять сценариев. Decision tree для запроса "как обновить одно свойство элемента инфоблока битрикс":
Decision tree:
Только NAME / ACTIVE / картинки? → Update без PROPERTY_VALUES.
Одно свойство по коду? → SetPropertyValuesEx или SetPropertyValues($id, $iblock, $val, 'CODE').
Добавить файл к множественному? → SetPropertyValueCode (append, не перезапись).
Полная синхронизация из 1С? → GetProperty → полный массив → Update с PROPERTY_VALUES.
D7 ElementTable::update? → только базовые поля; свойства - классический API.
| Метод | Когда выбирать | Затирание чужих свойств |
|---|---|---|
| Update без PROPERTY_VALUES | NAME, ACTIVE, картинки, разделы | Нет |
| Update + PROPERTY_VALUES | Полная выгрузка из 1С | Да, если массив неполный |
| SetPropertyValues + $PROPERTY_CODE | Одно свойство (4-й параметр) | Нет |
| SetPropertyValuesEx | Несколько кодов точечно | Нет |
| SetPropertyValueCode | Append к множественному файлу | Не перезаписывает весь multiple |
| D7 ElementTable::update | Только NAME, CODE, ACTIVE | Свойства не меняет (заблокирован) |
Без 4-го параметра SetPropertyValues = полная перезапись, как PROPERTY_VALUES. Делайте: Ex или SetPropertyValues с CODE. Не делайте: SetPropertyValues без CODE.
Обновите NAME, ACTIVE и картинки без PROPERTY_VALUES
Без ключа PROPERTY_VALUES свойства не меняются - только поля карточки.
$ok = $el->Update($elementId, [
'NAME' => 'Новое название', 'ACTIVE' => 'N', 'SORT' => 500,
]);
if (!$ok) { echo $el->LAST_ERROR; }
Картинки - через CFile::MakeFileArray. 'TIMESTAMP_X' => false не сдвигает дату. Не делайте: пустой PROPERTY_VALUES = array().
Избегите ловушки PROPERTY_VALUES: полная перезапись
Справка CIBlockElement::Update: при PROPERTY_VALUES нужен полный набор свойств инфоблока. Неуказанное удаляется для всех типов, кроме "файл" - файловые свойства не стираются молча, их удаляют явно через ['VALUE' => ['del' => 'Y']]. Значение false в массиве - не "не трогать", а участие в полной перезаписи.
На практике это классический pain с форума dev.1c-bitrix.ru: интегратор передал PRICE и три характеристики из семи - утром четыре поля пустые. В реальном проекте модератор советует SetPropertyValuesEx для точечных правок.
// ОПАСНО: 2 из 5 - остальные очистятся
$el->Update($id, ['PROPERTY_VALUES' => ['PRICE' => 1990]]);
// БЕЗОПАСНО: полный массив из GetProperty
$el->Update($id, ['PROPERTY_VALUES' => $fullProps]);
Для списка (select) передают ID enum, не текст "Да". ID vs VALUE - в гайде CIBlockPropertyEnum: списочное свойство.
Делайте: частичные правки - SetPropertyValuesEx. Не делайте: неполный PROPERTY_VALUES на проде.
Примените SetPropertyValues, SetPropertyValuesEx и SetPropertyValueCode
CIBlockElement::SetPropertyValuesEx($id, $iblockId, ['PRICE' => 2490]);
CIBlockElement::SetPropertyValues($id, $iblockId, 2490, 'PRICE');
SetPropertyValueCode добавляет файл к множественному, не затирая старые. Ex перезапишет весь multiple. Делайте: Update полей отдельно от Ex свойств.
Учтите ограничение D7 ORM: ElementTable не меняет свойства
ElementTable::update в D7 заблокирован для свойств - справка советует CIBlockElement::Update. ORM меняет только NAME, CODE, ACTIVE. Свойства PRICE, ARTICLE - через SetPropertyValuesEx.
\Bitrix\Iblock\ElementTable::update($id, ['NAME' => 'Новое']); // только поля
CIBlockElement::SetPropertyValuesEx($id, $iblockId, ['PRICE' => 1990]);
Делайте: поля через D7 или Update, свойства - классический API. Не делайте: ждать запись свойств от ElementCatalogTable::update.
Отладьте false по LAST_ERROR и ловушку OnBeforeIBlockElementUpdate
Update вернул false - $el->LAST_ERROR. Второй механизм пропажи - OnBeforeIBlockElementUpdate в init.php: без isset($arFields['PROPERTY_VALUES']) свойства обнуляются при Update полей. Разбор - гайд OnBeforeIBlockElementUpdate.
// ОПАСНО - затрет при любом Update
function myOnBefore(&$arFields) { $arFields['PROPERTY_VALUES']['X'] = 'y'; }
// БЕЗОПАСНО
function myOnBefore(&$arFields) {
if (!isset($arFields['PROPERTY_VALUES'])) { return; }
$arFields['PROPERTY_VALUES']['X'] = 'y';
}
- false: LAST_ERROR + ELEMENT_ID в лог.
- Пустые свойства: grep OnBeforeIBlockElementUpdate в init.php.
- Импорт: Update($id, $fields, false, false) - bUpdateSearch off; GetProperty до/после.
Схема импорта: GetProperty → Update полей → SetPropertyValuesEx → GetProperty → лог LAST_ERROR
Делайте: ищите оба механизма затирания. Не делайте: игнорировать false в cron.
Что дальше
Если пройдете чек-лист ниже, получите стабильный обмен: свойства не исчезают после ночного импорта, а результат Update виден в GetProperty до и после.
- Снимок GetProperty до/после на тестовом ID.
- Неполные PROPERTY_VALUES - на SetPropertyValuesEx.
- init.php: isset(PROPERTY_VALUES) - OnBeforeIBlockElementUpdate, enum ID - CIBlockPropertyEnum, Add vs Update - CIBlockElement::Add.
- Импорт ломает каталог - обсудите аудит обмена.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: Update, SetPropertyValues, SetPropertyValuesEx, ElementTable::update, форум dev.1c-bitrix.ru.
Частые вопросы
Почему после Update пропали свойства элемента?
Неполный PROPERTY_VALUES в вызове или обработчик OnBeforeIBlockElementUpdate без isset. Проверьте скрипт и init.php, восстановите из бэкапа или GetProperty. Подробнее - в гайде OnBeforeIBlockElementUpdate на mvmolkov.ru.
Как обновить одно свойство, не трогая остальные?
CIBlockElement::SetPropertyValuesEx($elementId, $iblockId, ['CODE' => $value]) или SetPropertyValues с четвертым параметром $PROPERTY_CODE. Не передавайте PROPERTY_VALUES в Update для одного свойства. Сверьте через GetProperty.
bitrix setproperty - какой метод выбрать?
SetPropertyValues без 4-го параметра = полная перезапись (как PROPERTY_VALUES). С параметром CODE - одно свойство. SetPropertyValuesEx - несколько кодов точечно. SetPropertyValueCode - append к множественному. Для полей - Update без PROPERTY_VALUES.
Чем Update отличается от SetPropertyValuesEx?
Update меняет поля и при PROPERTY_VALUES перезаписывает все свойства. SetPropertyValuesEx - только переданные коды. Для NAME/ACTIVE хватит Update без PROPERTY_VALUES.
OnBeforeIBlockElementUpdate - почему свойства очистились?
Обработчик в init.php трогает $arFields['PROPERTY_VALUES'] без isset - при Update только ACTIVE ядро получает неполный набор и обнуляет остальное. Проверьте isset и полный гайд по OnBeforeIBlockElementUpdate.
Можно ли обновить свойства через D7 ElementTable?
Нет. ElementTable::update заблокирован для свойств и меняет только базовые поля. Свойства - CIBlockElement::SetPropertyValuesEx или Update с полным PROPERTY_VALUES.
Update вернул false - где смотреть причину?
$el->LAST_ERROR сразу после вызова CIBlockElement::Update. Там права, валидация списка или ThrowException в OnBeforeIBlockElementUpdate. Логируйте ELEMENT_ID.