Парадокс, конечно, но это возможно. Казалось бы, причем тут класс ядра для работы со строками url. Но именно он может помочь нам в Joomla 4. Статья изначально была опубликована на Хабре. Копирую к себе.
Предисловие
Для улучшения скорости рендера страницы в браузере рекомендуют указывать атрибуты width
и height
для изображений. Естественно, удобно их заполнять автоматически. Подойти к решению задачи можно с разных сторон. Нужно помнить о том, что не стоит грузить при её решении сервер дополнительными обращениями, так как это будет влиять на скорость рендера страницы на стороне сервера.
Информация из данной заметки относится только к компонентам, использующим конструктор форм Joomla - Form
(ex JForm
), а так же использующим для вывода API Joomla.
Рендер изображений в HTML в Joomla
В коде для рендера может использоваться сразу класс HTMLHelper
с его методом image
, либо с помощью стандартных или переопределённых layouts
. Layout
- это макет вывода, который может использоваться в самых разных частях сайта. По своей логике использования он схож с 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
.
Для определения ширины и высоты файла картинки в 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
Когда вышла 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, указав размеры картинок в Ваших расширениях и при этом не грузить лишними обращениями сервер.
Минусы данного подхода
Минуса два:
-
Если Вы - не разработчик, или не умеете немного в PHP, полностью зависите от готовых расширений, то Вам данная инструкция вряд ли поможет. Не все разработчики Joomla учитывают подобные нюансы и используют API Joomla в работе. Но, если Вы умеете переопределять макеты в Joomla, то с помощью этой инструкции Вы можете сделать многое.
-
Замена файлов изображений по FTP. Если Вы любите менять картинки не через админку, а накатывать сверху по FTP новые файлы, оставив при этом старые названия, то новые размеры файла в базе данных не появятся сами. Хорошо, если Вы следите за размерами файлов и они не изменились или изменились не критично. Но если это совершенно другое изображение, других размеров и пропорций, то лучше делать замену через админку.
Upd: 14.08.2023. Дополнение.
Спустя некоторое время после публикации статьи на Хабре я продолжил изучение кода Joomla и статью теперь написал бы и назвал бы по-другому. Но уж как есть.
- Метод
HTMLHelper::image()
под капотом вызываетlayout
joomla.html.image
. Это означает, что рендер изображения происходит с помощью файлаlayouts/joomla/html/image.php
(который Вы можете, кстати, переопределить в своём шаблоне и вся Joomla будет будет использовать Ваш файл, а не стандартный). - В этом файле вызывается тот же самый метод
HTMLHelper
-cleanImageURL
. То есть то, что я предложил в тексте выше сделать ради получения атрибутовwidth
иheight
- по сути двойная работа, так как Joomla сама делает то же самое. - НО, единственное отличие от подхода, описанного в статье от того, что делает Joomla с изображениями в ядре - это то, какой путь для
<img src="/...">
приходит. Сама Joomla отдаёт путь так, как получила его из базы данных. То есть с#joomlaImage:://и-так-далее
. В то время как подход, описанный мною в статье выводит только путь к изображению.
С точки зрения СЕО лишние хвосты для изображений на картинки никак не повлияют. Поэтому какой именно подход использовать - решать Вам 😎