В списке вместо картинки появляется число: 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 (внутри цикла по элементам):
<?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 кто-то перезаписал поле. Откройте его и проверьте.
После правок шаблона список обновляется не сразу - сначала чистится кеш: кеш Битрикса: когда чистить и как не сломать.