Множественные свойства - вывод файлов, фильтр, удаление значений
Работаем с множественными свойствами: читаем набор значений, выводим файлы и удаляем одно значение, не потеряв остальные.
Решение
Читаем значения множественного свойства:
$res = CIBlockElement::GetList([], ['IBLOCK_ID' => 5, 'ID' => $elementId], false, false, ['ID', 'NAME', 'PROPERTY_MORE_PHOTO']);$photos = [];while ($row = $res->Fetch()) { $photos[] = $row['PROPERTY_MORE_PHOTO_VALUE']; // строка на каждое значение}printf("значений: %d\n", count($photos));Выборка отдаёт строку на каждое значение, а не одну строку с массивом. Элемент с пятью картинками придёт пятью строками, и это первое, обо что спотыкаются при подсчёте товаров.
Собираем значения одним вызовом:
$element = CIBlockElement::GetByID($elementId)->GetNextElement();$props = $element->GetProperties();// здесь VALUE уже массив, если свойство множественноеprint_r($props['MORE_PHOTO']['VALUE']);Этот способ возвращает свойства одним массивом и не размножает строки. Цена - отдельный запрос на каждый элемент, поэтому в списках его не применяют.
Выводим файлы множественного свойства:
foreach ((array)$props['MORE_PHOTO']['VALUE'] as $fileId) { $file = CFile::ResizeImageGet($fileId, ['width' => 300, 'height' => 300], BX_RESIZE_IMAGE_PROPORTIONAL, true); printf('<img src="%s" alt="">' . "\n", $file['src']);}В значении лежит идентификатор файла. Путь получают отдельным вызовом, и он же умеет сразу отдать уменьшенную копию нужного размера вместо исходника на несколько мегабайт.
Фильтруем элементы по множественному свойству:
$filter = [ 'IBLOCK_ID' => 5, 'PROPERTY_TAGS' => 'новинка', // есть хотя бы одно такое значение '!PROPERTY_COLOR' => $redEnumId, // нет ни одного такого значения];Обычное условие проверяет наличие хотя бы одного значения. Отрицание работает иначе: оно отбирает элементы, у которых такого значения нет ни в одной строке, а не те, у которых есть другое.
Удаляем одно значение из набора:
$values = (array)$props['MORE_PHOTO']['VALUE'];$values = array_diff($values, [$fileIdToRemove]);// файлам, которые надо удалить, передают признак удаленияCIBlockElement::SetPropertyValuesEx($elementId, 5, ['MORE_PHOTO' => $values]);Запись передаёт весь набор целиком. Передать одно оставшееся значение означает стереть остальные, а передать пустой массив - очистить свойство полностью.
Множественность и тип свойства - разные вещи. Множественным бывает и строка, и число, и файл, и привязка к элементам: флаг задаётся отдельно от типа. Поэтому одно и то же правило про запись целым набором действует для любого типа множественного свойства, а не только для картинок.
Значения множественного свойства хранятся отдельными строками и в том порядке, в котором их записали. Сортировать их выборкой нельзя: порядок задают при записи либо пересобирают в коде уже после чтения.
Типичные проблемы
Товаров в списке больше, чем на самом деле.
Выборка отдаёт строку на каждое значение множественного свойства. Один элемент с пятью значениями приходит пятью строками.
Вместо картинки выводится число.
В значении свойства лежит идентификатор файла, а не путь. Путь получают отдельным вызовом по этому идентификатору.
После записи остались только новые значения.
Запись передаёт весь набор целиком. Не перечисленные в массиве значения удаляются.
Отрицание в фильтре ведёт себя не так.
На множественном свойстве оно означает «нет ни одного такого значения», а не «есть значение, отличное от указанного».
Порядок значений меняется.
Сортировки у значений нет: они идут в порядке записи. Нужный порядок задают при сохранении либо пересобирают после чтения.
Частые вопросы
Как посчитать элементы, не размножая строки?
Через группировку по идентификатору элемента либо чтением свойств отдельным вызовом. Простой подсчёт строк выборки со множественным свойством даёт завышенное число.
Можно ли добавить одно значение, не трогая остальные?
Только прочитав текущий набор и записав его вместе с новым. Отдельного добавления одного значения в API нет.
Как вывести дополнительные картинки в списке товаров?
Перечислив свойство в параметрах компонента: он вернёт массив значений в результате. Отдельная выборка на каждый элемент списка обходится дороже.
Что происходит с файлом после удаления значения?
Он остаётся на диске, пока его не удалят явно. Освобождение места делают отдельной процедурой очистки неиспользуемых файлов.
Смежное
- Свойства инфоблоков - оглавление подтемы
- Хранение свойств инфоблока: две версии, скорость, выбор режима - почему множественные дублируют строки
- Свойства инфоблока: чтение, запись и фильтрация по значению - основы работы со свойствами
- Выборки из инфоблоков: GetList, ORM и разделы - почему строк больше, чем элементов
- Картинки товара при обмене: детальная, дополнительные, разделы - откуда берутся картинки
- Инфоблоки - устройство хранилища целиком
- Свойства-привязки: элемент, раздел и обратная выборка - множественная привязка и вывод названий
- Сопутствующие товары: связи, комплекты и подарки - привязка к элементам на практике