Работа с размерами изображений с помощью класса Uri в Joomla 4

Парадокс, конечно, но это возможно. Казалось бы, причем тут класс ядра для работы со строками url. Но именно он может помочь нам в Joomla 4. Статья изначально была опубликована на Хабре. Копирую к себе.

Предисловие

Для улучшения скорости рендера страницы в браузере рекомендуют указывать атрибуты width и height для изображений. Естественно, удобно их заполнять автоматически. Подойти к решению задачи можно с разных сторон. Нужно помнить о том, что не стоит грузить при её решении сервер дополнительными обращениями, так как это будет влиять на скорость рендера страницы на стороне сервера.

Информация из данной заметки относится только к компонентам, использующим конструктор форм Joomla - Form (ex JForm), а так же использующим для вывода API Joomla.

Рендер изображений в HTML в Joomla

В коде для рендера может использоваться сразу класс HTMLHelper с его методом image, либо с помощью стандартных или переопределённых layoutsLayout - это макет вывода, который может использоваться в самых разных частях сайта. По своей логике использования он схож с trait в php - "оторванный от контекста" фрагмент логики. В случае с layout - вывод с предобработкой. Часто внутри layout конечный рендер изображения происходит не простым echo '<img src='.$img_src.'/>', а тем же методом HTMLHelper::image();

Метод HTMLHelper::image() в Joomla

Метод производит рендер изображения со всеми переданными ему атрибутами. Очень удобно с ним работать следующим образом:

<?php
use Joomla\CMS\HTML\HTMLHelper;

$img_attribs = [
	'class' => 'w-100 h-auto',
	'width' => '100',
	'height' => '100',
	'loading' => 'lazy',
];

echo HTMLHelper::image($img_src, $img_alt, $img_attribs); 

Метод HTMLHelper::image принимает на вход:

  • путь до изображения;

  • атрибут alt для него;

  • дополнительные атрибуты, какие Ваша душа пожелает.

3-й параметр для всех остальных атрибутов может быть как просто строкой, так и массивом. Таким образом можно добавить массово любые атрибуты для изображений, например, data-атрибуты или уникальные id, которые будут использоваться на js-фронте.

Изображения в Joomla 3

В Joomla 3 поле типа media для выбора картинок в панели администратора заполняется относительным путём до файла вида images/my_file.jpg.

Поле media для выбора изображений в Joomla 3
Поле media для выбора изображений в Joomla 3

Для определения ширины и высоты файла картинки в Joomla 3 можно было использовать следующую конструкцию:

<?php 
$size        = getimagesize(JPATH_SITE.'/'.$img_src);
$img_attribs = [
	'class'  => 'w-100 h-auto',
	'width'  => $size[0],
	'height' => $size[1],
];
echo HTMLHelper::image($img_src, $img_alt, $img_attribs); 

Функция getimagesize возвращает размеры изображения в разных форматах, которые уже можно передать в HTMLHelper. Но и сама Joomla 3 в целом не поддерживала формат webp, да и функция getimagesize начала поддерживать этот формат только с php 7.1, но не всегда верно обрабатывать файл, поэтому в сети немало решений с использованием imagecreatefromwebp. В то время, как этот формат является одной из рекомендаций по оптимизации скорости загрузки сайта Google Page Speed.

Изображения в Joomla 4

В Joomla 4 же стандартный медиа-менеджер вставляет в поля не просто путь изображения, а путь, дополненный параметрами вида images/headers/blue-flower.jpg#joomlaImage://local-images/headers/blue-flower.jpg?width=700&height=180

Поле типа media для выбора изображений в Joomla 4.
Поле типа media для выбора изображений в Joomla 4.

Когда вышла Joomla 4 многие (в том числе и я) не поняли, баг это или фича 🤣. GET-параметры к изображению не отображают другую картинку, но для поисковых систем это другой url, а следовательно другой файл. У СЕО-специалистов начинают шевелиться волосы... Время показало, что это скорее фича, просто нужно уметь её готовить.

Вариант получения размеров изображения при каждой генерации страницы утяжеляет рендер страницы в целом. Поэтому логично определить размеры изображения заранее и хранить их в базе, вместе с информацией о самом изображении (пути к нему).

Именно таким образом сейчас и работает Joomla 4. Когда Вы в админке выбираете изображение - медиа-менеджер определяет размер картинки и сохраняет в виде GET-параметров к URL картинки.

В своих макетах или layout Вы можете работать с картинками следующим образом.

Получить чистый путь к картинке без #joomlaImage://local-images...

Для этого в Joomla 4 в HTMLHelper появился метод cleanImageURL:

<?php
use Joomla\CMS\HTML\HTMLHelper;

$img_src = HTMLHelper::_('cleanImageURL', $displayData['src']);

Получить размеры файла картинки с помощью класса Uri

Поскольку images/headers/blue-flower.jpg#joomlaImage://local-images/headers/blue-flower.jpg?width=700&height=180 по сути является url - мы можем работать с ним с помощью класса ядра Joomla Uri. Таким образом нам будет удобно получить любой параметр из этой строки.

Для этого нам нужно:

  • получить часть строки после символа #;

  • создать новый класс Joomla\CMS\Uri\Uri;

  • получить нужный параметр url с помощью метода getVar('attr_name').

Итак, пример кода

<?php
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;

$img_src = 'images/headers/blue-flower.jpg#joomlaImage://local-images/headers/blue-flower.jpg?width=700&height=180';
$img_alt = 'Атрибут alt для картинки';

$img_attribs = [
	'class' => 'w-100 h-auto', // указываем CSS-класс для картинки, можно из параметров, а не хардкодом
];

// Разделяем строку по символу # с помощью explode. 
// Получаем массив с двумя элементами, где 2-й элемент - url с параметрами
$img_params_array = explode('#', $img_src);

// Создаём объект Uri
$uri = new Uri($img_params_array[1]);

// Получаем размеры картинки
$img_attribs['width'] = $uri->getVar('width');
$img_attribs['height'] = $uri->getVar('height');

// Если работаем в цикле, то по итератору определяем каким изображениям нужен
// атрибут loading=lazy. Как правило для картинок в первом экране или нескольких 
// первых картинках он не нужен.
//
// if($i > 0){
//	$img_attribs['loading'] = 'lazy';
// }

// Получаем чистый путь до картинки, если СЕО-специалисты очень просят.
$img_clean_src = HTMLHelper::_('cleanImageURL', $img_src);

// Рендер изображения
echo HTMLHelper::image($img_clean_src, $img_alt, $img_attribs); 

Вот таким образом можно оптимизировать сайт на Joomla 4, указав размеры картинок в Ваших расширениях и при этом не грузить лишними обращениями сервер.

Минусы данного подхода

Минуса два:

  1. Если Вы - не разработчик, или не умеете немного в PHP, полностью зависите от готовых расширений, то Вам данная инструкция вряд ли поможет. Не все разработчики Joomla учитывают подобные нюансы и используют API Joomla в работе. Но, если Вы умеете переопределять макеты в Joomla, то с помощью этой инструкции Вы можете сделать многое.

  2. Замена файлов изображений по FTP. Если Вы любите менять картинки не через админку, а накатывать сверху по FTP новые файлы, оставив при этом старые названия, то новые размеры файла в базе данных не появятся сами. Хорошо, если Вы следите за размерами файлов и они не изменились или изменились не критично. Но если это совершенно другое изображение, других размеров и пропорций, то лучше делать замену через админку.

Upd: 14.08.2023. Дополнение.

Спустя некоторое время после публикации статьи на Хабре я продолжил изучение кода Joomla и статью теперь написал бы и назвал бы по-другому. Но уж как есть. 

  1. Метод HTMLHelper::image() под капотом вызывает layout joomla.html.image. Это означает, что рендер изображения происходит с помощью файла layouts/joomla/html/image.php (который Вы можете, кстати, переопределить в своём шаблоне и вся Joomla будет будет использовать Ваш файл, а не стандартный).
  2. В этом файле вызывается тот же самый метод HTMLHelper - cleanImageURL. То есть то, что я предложил в тексте выше сделать ради  получения атрибутов width и height - по сути двойная работа, так как Joomla сама делает то же самое. 
  3. НО, единственное отличие от подхода, описанного в статье от того, что делает Joomla с изображениями в ядре - это то, какой путь для <img src="/..."> приходит. Сама Joomla отдаёт путь так, как получила его из базы данных. То есть с #joomlaImage:://и-так-далее. В то время как подход, описанный мною в статье выводит только путь к изображению.

С точки зрения СЕО лишние хвосты для изображений на картинки никак не повлияют. Поэтому какой именно подход использовать - решать Вам 😎

 

Толкачев Сергей Юрьевич
Толкачев Сергей Юрьевич

Joomla-разработчик. Контрибьютер ядра Joomla. Один из ведущих Telegram-канала русскоязычного Joomla-сообщества JoomlaFeed, один из модераторов чата русскоязычного Joomla-сообщества. Мои расширения в официальном маркетплейсе расширений Joomla - Joomla Extensions Directory. Имею публикации в официальном журнале международного Joomla-сообщества - Joomla Community Magazine.

Муж. Отец 3 детей.

Россия, Саратов.

Расширения Joomla WebTolk

90 Всего расширений
11 Категорий
399 Выпущено версий
387363 Всего скачиваний
Корзина
Корзина пуста