Перейти к содержимому

Значение свойства не сохраняется - разбор причин

Скрипт отработал без единой ошибки, а значение свойства у элемента пустое или прежнее. Разбираем причины по убыванию частоты.

С чего начать

Смотрим, что реально лежит у элемента:

$res = CIBlockElement::GetProperty($iblockId, $elementId, [], ['CODE' => 'COLOR']);
while ($row = $res->Fetch()) {
printf("%s value=%s enum=%s\n", $row['CODE'], $row['VALUE'], $row['VALUE_ENUM']);
}
// пусто - значение не записалось; чужое значение - записалось не туда

Чтение по свойству отделяет проблему записи от проблемы вывода. Пустое значение означает разбор со стороны кода записи, а непустое переводит поиск в шаблон вывода.

Проверяем идентификаторы вариантов списка:

$res = CIBlockPropertyEnum::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => 'COLOR']);
while ($v = $res->Fetch()) {
printf("%d = %s\n", $v['ID'], $v['VALUE']);
}
// в свойство-список пишут идентификатор варианта, а не его текст

Списочное свойство хранит ссылку на вариант, а не строку. Переданный текст записывается как пустота, и ошибки при этом не возникает: платформа просто не находит такой вариант.

Пишем свойства по одному, не трогая соседние:

CIBlockElement::SetPropertyValuesEx($elementId, $iblockId, ['COLOR' => $enumId]);
// коды здесь регистрозависимы, в отличие от выборки
// очистка множественного свойства - false, а не пустой массив

Частичная запись меняет только названные свойства. Полная запись массивом обнуляет всё, чего в массиве нет, и это самая частая причина «пропали остальные свойства».

Проверяем свойство-привязку до записи:

$prop = CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => 'BRAND'])->Fetch();
printf("тип=%s связанный инфоблок=%s множественное=%s\n",
$prop['PROPERTY_TYPE'], $prop['LINK_IBLOCK_ID'], $prop['MULTIPLE']);
// привязка к чужому инфоблоку не сохранится: цель ищется только в связанном

Настройки свойства объясняют половину неудачных записей. Связанный инфоблок, множественность и тип определяют, что вообще можно передать в это свойство и в каком виде.

Причины

  1. В свойство-список передан текст вместо варианта примерно 30% случаев

    ПризнакОшибок нет, значение остаётся пустым, в базе у свойства нет ссылки на вариант.

    ПроверкаЧитаем список вариантов свойства и сверяем идентификаторы с тем, что передаёт код.

    Что делатьПередаём идентификатор варианта: текст платформа сопоставить не пытается.

  2. Полная запись обнулила остальные свойства примерно 25% случаев

    ПризнакЗаписанное свойство на месте, а прочие свойства элемента опустели разом.

    ПроверкаСмотрим, каким вызовом идёт запись и передаётся ли туда полный набор свойств.

    Что делатьПереходим на частичную запись по кодам: она не трогает свойства, которых нет в вызове.

  3. Код свойства написан в другом регистре примерно 20% случаев

    ПризнакОдин и тот же код работает при выборке и молчит при записи.

    ПроверкаСравниваем регистр кода в вызове записи с кодом свойства в настройках инфоблока.

    Что делатьПриводим код к тому же виду: при частичной записи регистр имеет значение.

  4. Привязка не находит целевой элемент примерно 15% случаев

    ПризнакСвойство-привязка пустое, хотя целевой элемент существует и открывается.

    ПроверкаПроверяем привязку свойства к нужному инфоблоку и активность целевого элемента.

    Что делатьПередаём идентификатор цели, а для множественного свойства добавляем значение, а не заменяем все.

  5. Множественное файловое свойство меняют в несколько заходов примерно 10% случаев

    ПризнакПосле обновления часть файлов исчезла или задвоилась.

    ПроверкаСмотрим, сколько вызовов записи приходится на одно свойство в рамках одной операции.

    Что делатьСобираем удаление и добавление файлов в один вызов: после операции идентификаторы значений меняются.

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

Почему при записи не возникает ошибки?

Запись свойств не проверяет содержимое так строго, как поля элемента. Несуществующий вариант списка или чужой элемент привязки просто не сохраняются, а вызов считается успешным.

Как очистить множественное свойство?

Передать признак пустого значения, а не пустой массив: пустой массив во многих версиях означает «ничего не менять». Проверять результат надо чтением значений после записи.

Почему свойство не видно в выборке через ORM?

У свойства не заполнен символьный код. В карту класса попадают только свойства с кодом, и без него обращаться к ним по имени не получится.

Нужно ли сбрасывать кэш после записи свойств?

Да, частичная запись кэш не чистит. Страница будет показывать старое значение до сброса кэша или до истечения его времени жизни.

Как записать значение свойству нескольких тысяч элементов?

Порциями, с частичной записью и без переиндексации поиска на каждом шаге. Полная запись элемента на таком объёме и медленнее, и опаснее для соседних свойств.

Смежное

Первоисточник