PREVIEW_PICTURE выводится числом вместо картинки

Коротко

В списке вместо картинки появляется число: PREVIEW_PICTURE - это ID файла. Один вызов CFile::ResizeImageGet принимает и ID, и массив - и отдаёт готовую уменьшенную копию.

Симптом
Вместо картинки в списке - число

Карточка в списке новостей должна показывать обложку, а на экране - цифра вроде 105. Шаблон сунул $arItem["PREVIEW_PICTURE"] прямо в src, а в собственной выборке в этом поле лежит число-ID.

Причина
PREVIEW_PICTURE - это ID файла

В таблице элементов инфоблока обложка - это число: ID файла, который ссылается на запись в таблице b_file. Сам путь до картинки появляется после того, как Битрикс подтянет файл по этому ID.

Инфоблок - хранилище однотипных записей: новости, товары, заявки, а элемент - запись внутри него.

Отсюда разница, которая всех путает: у штатных компонентов iblock-семейства (news.list, news и др.) в component.php вызывается \Bitrix\Iblock\Component\Tools::getFieldImageData() - он прогоняет поле через CFile и в шаблон придёт массив с ключами SRC, WIDTH и другими, а в собственной выборке (свой CIBlockElement::GetList со своим arSelect или запрос на D7 ORM) приходит то, что лежит в базе, - буквально число-ID, и шаблон печатает его как есть.

Решение
Один вызов CFile::ResizeImageGet закрывает оба случая

Метод CFile::ResizeImageGet принимает в первый аргумент и ID файла, и массив данных файла - проверять, что именно пришло, не нужно.

Полный блок вставки обложки в шаблоне news.list (внутри цикла по элементам):

шаблон news.list, цикл по элементам
<?php
// $arItem - текущая строка выборки
$preview = null;
if (!empty($arItem["PREVIEW_PICTURE"])) {
    $preview = CFile::ResizeImageGet(
        $arItem["PREVIEW_PICTURE"],   // ID или массив - оба варианта подходят
        ["width" => 360, "height" => 240],
        BX_RESIZE_IMAGE_PROPORTIONAL,
        true                          // вернуть массив с шириной и высотой
    );
}
if ($preview) {
    echo '<img src="' . $preview["src"] . '"'
        . ' width="' . $preview["width"] . '" height="' . $preview["height"] . '"'
        . ' loading="lazy" alt="' . htmlspecialcharsbx($arItem["NAME"]) . '">';
}

После этого на странице появляется уменьшенная копия - метод положит её в кеш и отдаст готовый src, а исходный файл на сервере остаётся целым.

Про регистр ключей: ResizeImageGet возвращает их в нижнем - src, width, height. А у CFile::GetFileArray (она отдаёт ссылку на полную, не обрезанную картинку) ключи в верхнем - SRC, WIDTH, HEIGHT; тот же верхний регистр у массива из штатного news.list, только там добавляются ALT и TITLE. Смешать регистры - самый частый способ получить пустой src в шаблон.

✓ Делайте так

  • выводите обложку через CFile::ResizeImageGet - метод примет и число, и массив;
  • в alt ставьте заголовок новости - он и человеку нужен, и поискам;
  • задавайте width и height явно, иначе страница прыгает при загрузке.

✗ Так не делайте

  • не рассчитывайте, что в своём GetList поле вернётся массивом - там всегда ID; конвертируйте через ResizeImageGet;
  • не собирайте путь картинки руками (/upload/...) - он лежит в b_file;
  • не путайте регистр ключей: у ResizeImageGet - lowercase, у GetFileArray - uppercase.

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

Как вывести полную картинку без сжатия?

$ar = CFile::GetFileArray($id); echo $ar["SRC"]; - вернёт полный URL на исходный файл. Для обложки в списке обычно не нужно: вес большой.

Почему массив в одном списке и число в другом?

Первый случай - штатный iblock-компонент: он сам прогоняет поле через getFieldImageData() и раздаёт массив со всеми ключами. Второй - ваша собственная выборка или запрос на ORM: вы получаете то, что в базе, - ID. Ещё вариант: в result_modifier.php кто-то перезаписал поле. Откройте его и проверьте.

После правок шаблона список обновляется не сразу - сначала чистится кеш: кеш Битрикса: когда чистить и как не сломать.

Не получается?

Сам не получилось - не страшно, я такое чиню регулярно. Напишите в Telegram или оставьте заявку - разберёмся.

Что дальше:

Константин - Разработчик 1С-Битрикс: чинит и дорабатывает сайты на БУС, пишет код сам.
Этот и другие разборы с меткой БУС - его живая практика. @bitrix_praktik