В API Joomla есть полезный инструмент - класс HTMLHelper. Он выводит HTML-элементы интерфейса с нужными параметрами: модальные окна, аккордеоны, табы, изображения и т.д. Для рендера мы передаём все нужные данные: заголовки окон, содержимое табов, атрибуты изображений. Плюс использования HTMLHelper в Joomla - это его универсальность, оторванность от контекста, а это значит, что его можно использовать везде. А также возможность использования логики при рендере в зависимости от вводных данных. Опубликовал эту статью на Хабре. Копирую к себе.

Ранее писал о том как:

Но это был обзор возможностей стандартных классов HTMLHelper. А что если нам нужно создать свой?

Создание собственного класса HTMLHelper в Joomla 4 / Joomla 5

Прежде всего посмотрим на то, как оно работает в Joomla 4+. Типичный вывод с помощью HTMLHelper выглядит так:

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

$img_src = 'images/banner.webp';
$img_attribs = [
    'loading' => 'lazy',
    'class'=>'img-fluid',
    'data-custom-attr'=>'your-custom-data-attr-value',
    'title'=> 'Title attribute for image'
];
echo HTMLHelper::_('image', $img_src, 'Alt text for image', $img_attribs, true, 1);

// или вот так

$identifier = 'elementId';
$params = ['array'=> 'of params'];
echo HTMLHelper::_('bootstrap.renderModal', $identifier, $params);

Нас интересует 2-й вариант - метод HTMLHelper::_(). Ссылки на метод: \Joomla\CMS\HTML\HTMLHelper::_ (), файл libraries/src/HTML/HTMLHelper.php. Это метод-загрузчик классов.

Аргументы метода HTMLHelper::_()

$key - имя ресурса в реестре классов для HTMLHelper, которое выглядит следующим образом: (prefix).(class).functionPrefix - это неймспейс класса, если нужен. Class - собственно имя файла и класса по PSR-4. Prefix и Class являются опциональными. Главное, чтобы имя ресурса было уникальным. Function - имя метода в классе. Так, пример с HTMLHelper::_('bootstrap.renderModal') будет искать в реестре ресурс с именем bootstrap и найдет его.

Класс HTMLHelper Bootstrap Joomla 5 скриншот в PHPStorm 
Класс HTMLHelper Bootstrap Joomla 5 скриншот в PHPStorm

И в классе \Joomla\CMS\HTML\Helpers\Bootstrap будет вызывать метод renderModal, куда и будут переданы дальнейшие аргументы метода HTMLHelper::_().

Создаём свой класс

Таким образом наша задача сводится к тому, чтобы написать класс с методами для рендера HTML нужных элементов интерфейса и с помощью системного плагина подключить его в реестр ресурсов HTMLHelper. В методах нашего класса HTMLHelper мы будем использовать стандартный механизм Joomla Layouts.

Почитать: Создание плагинов с учётом новой структуры Joomla 4. Также в хабе Joomla на Хабре есть ещё ряд статей, рассказывающих о создании различных типов плагинов.

Системный плагин

Если мы работаем с Joomla 4+, то нам подойдёт событие onAfterRoute(). В Joomla 5 появилось событие onAfterInitialiseDocument, которое было создано специально для подобных случаев. Используем метод HTMLHelper::getServiceRegistry() для добавления своего класса в реестр классов Joomla HTMLHelper.

<?php 
namespace Joomla\Plugin\System\Myplugin\Extension;

defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;

class Myplugin extends CMSPlugin implements SubscriberInterface
{

	public static function getSubscribedEvents(): array
	{
		return [
			'onAfterRoute' => 'onAfterRoute',
		];
	}

	/**
	 * @return void
	 *
	 * @since 1.0.0
	 *
	 */
	public function onAfterRoute(): void
	{
		HTMLHelper::getServiceRegistry()
			->register(
				'webtolk',
				\Joomla\Plugin\System\Myplugin\HTML\Webtolk::class
			);
	}
}

Пользовательский класс HTMLHelper в плагине

В нашем плагине в папке src создадим папку HTML, в которой будет лежать класс, например, Webtolk.

Файловая структура плагина Joomla 5 для регистрации собственного класса HTMLHelper
Файловая структура плагина Joomla 5 для регистрации собственного класса HTMLHelper

Код пользовательского класса HTMLHelper будет выглядеть следующим образом:

<?php
namespace Joomla\Plugin\System\Myplugin\HTML;

use Joomla\CMS\Layout\LayoutHelper;

defined('_JEXEC') or die;

/**
 * @since  1.0.0
 */
abstract class Webtolk
{
	/**
	 * @param  int  $key  Any digit
	 *
	 * @return string
	 *
	 * @since 1.0.0
	 */
	public static function indicator(int $key): string
	{
		$html = '';
		if (!empty($key))
		{
			$html = LayoutHelper::render(
				'indicator.green',
				['key' => $key],
				JPATH_SITE . '/plugins/system/myplugin/layouts'
			);
		}
		
		return $html;
	}
}

Таких методов в классе может быть несколько и каждый из них будет оперировать своими входными данными и возвращать свои макеты.

Отличительная особенность классов HTMLHelper состоит в том, что в них можно реализовывать логику, которая напрямую влияет на отображение. Это могут быть дочерние элементы, значения по умолчанию, подключение необходимых Web Assets и так далее. Таким образом логика остаётся в классах, а вёрстка остаётся в макетах (layouts).

Файл макета вывода пользовательского класса HTMLHelper

Осталось создать макет вывода, где собственно будет находиться вёрстка. Мы реализуем его с помощью стандартного для Joomla механизма Layouts (Layouts и subLayouts в Joomla). В Joomla есть понятие layout. Это кусочек вёрстки, который можно многажды использовать в любом месте сайта: как в панели администратора, так и во фронтенде. Можно рассматривать лейауты как оторванные от контекста элементы дизайна. Находятся они в папке layouts в корне сайта. Как их использовать? Один из вариантов - использование LayoutHelper.

<?php
use Joomla\CMS\Layout\LayoutHelper;

// $item - ваш объект или массив с данными, которые нужно использовать  в верстке

echo LayoutHelper::render('components.swjprojects.project.icons', ['item' => $item]);

1-й аргумент - это dot-separated (разделенный точками) путь к файлу лейаута. Название папки "layouts" в данном случае пропускается как само собой разумеющееся. Внутрь файла приходит массив $displayData, в котором будут лежать наши данные - $key $displayData['key']. Но в нашем плагине мы сказали LayoutHelper искать макет не только по стандартным путям (в папке layouts от корня), но и в папке плагина:

<?php
use Joomla\CMS\Layout\LayoutHelper;

$html = LayoutHelper::render(
				'indicator.green', // Путь к файлу [$basePath]/indicator/green.php
				['key' => $key], // массив данных $displayData
				JPATH_SITE . '/plugins/system/myplugin/layouts' //[$basePath] для поиска макетов
			);

3-й аргумент LayoutHelper::render() - $basePath - это путь, относительно которого будет применяться dot-separated путь, последняя часть которого - имя файла без расширения.

Само содержимое файла /plugins/system/myplugin/layouts/indicator/green.php примитивно:

<?php
/** @var array $displayData  Массив с данными для рендера */
extract($displayData);
/** @var int $key  Переменная $key, которую передавали в echo HTMLHelper::_('webtolk.indicator',1111); */
dump($key);

Результат

Теперь абсолютно везде в Joomla мы можем использовать простой рендер нужного элемента интерфейса одной строчкой:

<?php
use Joomla\CMS\HTML\HTMLHelper;
defined('_JEXEC') or die;

$key = 1111;
echo HTMLHelper::_('webtolk.indicator', $key);

Заключение

В заключение хочу сказать спасибо Joomla-разработчику Виталию Некрасову, у которого я частично подглядел этот подход и это способствовало появлению данной статьи.

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

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

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

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

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

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