Как тестировать Joomla PHP-разработчику? Компонент Patch tester.
Joomla - open source PHP-фреймворк с готовой админкой. Его основная разработка ведётся на GitHub. Для того, чтобы международному сообществу разработчиков было удобнее тестировать Pull Requests был создан компонент Patch Tester, который позволяет "накатить" на текущую установку Joomla именно те изменения, которые необходимо протестировать.
На стороне инфраструктуры Joomla для каждого PR собираются готовые пакеты, в которых находится ядро + предложенные изменения. В каждом PR обычно находятся инструкции по тестированию: куда зайти, что нажать, ожидаемый результат. Тестировщики могут предположить дополнительные сценарии, исходя из своего опыта и найти баги, о которых сообщить разработчику. Или не найти, и тогда улучшение или исправление ошибки быстрее войдёт в ядро Joomla.
Напомню, что для того, чтобы PR вошёл в ядро Joomla нужны минимум 2 положительных теста от 2 участников сообщества, кроме автора.
WT IndexNow плагин для Joomla - отправка страниц сайта на переиндексацию в поисковые системы.
Пакет плагинов, обеспечивающий ручную и автоматическую отправку url адресов Joomla в поисковые системы на переиндексацию по протоколу IndexNow.
Согласно документации протокол поддерживают все крупнейшие поисковые системы, кроме Google. Протокол служит для получения от сайтов URL, которые нужно переиндексировать заново или проиндексировать в первый раз как можно быстрее. Отправка адресов сайта таким образом существенно ускорит индексацию нового или изменённого контента поисковыми системами.
Поисковые системы по этому протоколу обмениваются друг с другом данными, поэтому отправив URL в одну из них вы сообщаете их сразу всем.
Протокол IndexNow поддерживают:
Amazon
Microsoft Bing
Naver
Seznam.cz
Yandex
Yep
Суточный лимит URL - 10000 в сутки. Возможна отправка вручную и автоматически. Пакетом поддерживаются:
материалы и категории материалов Joomla
контакты и категории контактов Joomla
SW JProjects - компонент каталога расширений для Joomla
JoomShopping - компонент интернет-магазина для Joomla
Метод registerListeners() в CMSPlugin в плагинах планируется удалить в Joomla 7.0.
Этот метод регистрирует устаревшие слушатели событий в диспетчере, имитируя работу плагинов Joomla! 3.x и ниже для Joomla 4+. По умолчанию этот метод ищет все общедоступные методы, название которых начинается с on. Он регистрирует лямбда-функции (замыкания), которые пытаются преобразовать аргументы отправленного события в аргументы вызова метода и вызвать ваш метод on<Нечто>. Результат передаётся обратно событию в его аргумент result.
Теперь этот слой совместимости с устаревшей Joomla 3 помечен к удалению в Joomla 7.0, которая должна выйти осенью 2027 года. Это означает, что те уникальные расширения от Joomla 2.5 / Joomla 3, которые ещё работали на Joomla 4-6 скорее всего окончательно перестанут работать на Joomla 7. Предполагается, что активные разработчики планомерно и постепенно избавляются от технического долга и обновляют свои расширения 😎
Совет по Joomla: использовать выключенное состояние для кнопок в списках элементов админки - listCheck().
Мы добавляем в тулбар панели администратора Joomla некую кнопку, которая что-то делает со списком id выделенных элементов и ajax-запросом отсылаем их в свой плагин. Но нам надо предупредить нажатия на кнопку в тех случаях, когда ни один элемент не был выбран. Для этого можно написать свою проверку на js. А можно воспользоваться встроенной в Joomla.
Добавить кнопку в тулбар Joomla 6.
use Joomla\CMS\Toolbar\Button\BasicButton;
use Joomla\CMS\Language\Text;
// ниже по коду, где-нибудь в плагине на onAfterDispatch()
// Предварительно проверяем в каком компоненте мы находимся по option из $app->getInput()
// пример из плагина, поэтому $this->getApplication()
$app = $this->getApplication();
// Берём текущий тулбар
$toolbar = $app->getDocument()->getToolbar('toolbar');
// Создаём кнопку
$button = (new BasicButton('send-to-indexnow'))
->text(Text::_('PLG_WTINDEXNOWSWJPROJECTS_BUTTON_LABEL'))
->icon('fa-solid fa-arrow-up-right-dots')
->onclick("window.wtindexnowswjprojects()");
// Добавляем кнопку в тулбар
$toolbar->appendButton($button);
Заблокировать кнопку тулбара Joomla, если не выбраны элементы списка.
Теперь нам надо проверить находимся ли мы в списке. Делаем это по view из $app->getInput().
И если мы в списке - используем метод $button->listCheck(true), который сделает проверку за нас. Если ни один элемент не выбран - кнопка в тулбаре Joomla будет заблокирована и JS-обработчик не будет вызван. Этот метод есть у всех классов кнопок, наследующих класс \Joomla\CMS\Toolbar\ToolbarButton.
Хочу написать о финте, который позволит вам сохранить нервы и сэкономить время. Правда некоторые (многие, почти все) впадают в ступор от него. Поэтому тут использована КДПВ с поста. Я наверно чувак слева.
А именно добавление первым условием if единицы:
if (1
&& $cond1
&& $cond2
&& $cond3
)
Использование финта дает нам возможность: 1. Быстро выключать фичу заменой 1 на 0:
if (0
&& $cond1
&& $cond2
&& $cond3
)
2. Быстро выключать любое условие в PhpStorm через горячие клавиши:
if (1
// && $cond1
&& $cond2
&& $cond3
)
Без этого финта мы не можем быстро выключить первое условие. Нам приходится делать примерно такую фигню, манипулируя с двумя строками и целясь в &&:
if (
/*$cond1
&&*/ $cond2
&& $cond3
)
Или такую:
if (
$cond2
&& $cond3
)
3. Быстро добавлять новое первое условие:
if (1
&& $cond2
&& $cond3
)
легко превращается в:
if (1
&& $cond1 // в изменениях одна строка
&& $cond2
&& $cond3
)
4. Быстро дублировать любое условие.
5. Быстро менять порядок условий.
6. Также у нас будет чистый diff git-а при удалении/добавление первого условия. Тут должен быть рисунок удаления с финтом и без, рисунок добавления с финтом и без. Также при конфликте у нас будет более простое его решение, если нужно просто добавить оба условия.
Данный финт сродни правилу хорошего тона добавлять после последнего элемента массива запятую. Это дает нам возможность при добавлении работать только с одной строкой. Добавлять горячими клавишами дублирования строк, в diff опять же будет только 1 строка, а также при конфликте слияний просто применяем обе строки и не нужно проставлять запятые, а то код упадет.
[ВИДЕО] AmoCRM + Joomla: быстрая настройка интеграции. Библиотека WT AmoCRM.
- Как быстро настроить интеграцию AmoCRM и сайта на Joomla?
- использовать PHP библиотеку WT AmoCRM для Joomla, которая предполагает использование её разработчиками. А разработчики могут написать любое количество плагинов и решений по интеграции и автоматизации AmoCRM и Joomla.
Человек на GitHub ускорил Joomla в 600 раз на объёме 150к+ материалов в 1700+ категориях.
На старте его сайт на Joomla 3 вообще не смог обновиться на Joomla 5. Пришлось делать экспорт/импорт материалов. Проделав всё это он запустил-таки этот объём данных на Joomla 5. Тестовый скрипт грузил 200 материалов из этого объёма всего за 94 секунды ))) А главная страница с категориями грузилась 20 секунд.
Добавив индекс для таблицы #__content
CREATE INDEX idx_catid_state ON #__content (catid, state);
он сократил время загрузки категорий до 1 секунды. Затем наш герой решил поковырять SQL-запрос в ArticleModel, который отвечает за выборку материалов. И решил заменить тип JOIN на STRAIGHT_JOIN для категорий.
Что сократило загрузку 200 материалов из 150к с 94 секунд до 5. К слову сказать, боевой сайт на Joomla 3 крутится на 12CPU 64GB рамы. А все манипуляции с кодом он делает на базовом 1CPU 1GB сервере и замеры скорости даны именно для базового сервера.
Но это всё в дискуссии, хотя в идеале должно вылиться в Pull Requests. Дальнейшие его изыскания и результаты можно поглядеть в дискуссии на GitHub. Это ещё не конец.
Мы - Open Source сообщество, где никто никому ничего не должен. Джунгли. Но человек ищет пути оптимизации Joomla и предлагает решения. Если оказать поддержку и предложить помощь хотя бы с тестированием самых разнообразных сценариев, то возможно эти улучшения смогут войти в ядро. Пусть не быстро, пусть через несколько лет, пусть не все, но войдут. Достаточно предложить руку помощи и приложить немного усилий.
Обработка HTTP ответа в Joomla 6+. Изменения по сравнению с Joomla 3 - Joomla 5.
В Joomla для выполнения внешних запросов из PHP к сторонним API используется класс Joomla\Http\Http напрямую или же Joomla\Http\HttpFactory, который возвращает для работы преднастроенный по умолчанию класс Http. О работе с HTTP-запросами подробно рассказывалось в статье 2021 года Создание внешних запросов с использованием HttpFactory (Joomla) (на Хабре), (на сайте автора). Некоторые изменения касаются работы с ответами на запросы. Например, наш запрос:
use Joomla\Http\HttpFactory;
$http = (new HttpFactory)->getHttp($options, ['curl', 'stream']);
$response = $http->get('https://any-url.ru/api/any/endpoint');
Раньше можно было получить код ответа или тело ответа как свойство $response - $response->code или $response->body. Однако, Joomla, начиная с Joomla 4 во многом переходит на стандарты PSR. В частности для работы с HTTP-ответами - на PSR-7. Также хорошая статья на Хабре о PSR-7: PSR-7 в примерах.
Прямое обращение к свойствам code, headers, body объявлено устаревшим в Joomla 6.0.0 и обещают удалить в Joomla 7.0.0.
Вместо этого нужно работать с HTTP-ответом по стандартам PSR-7.
Код ответа. Было $response->getContents(). Стало $response->getStatusCode().
Заголовки ответа.
Было $response->headers. Стало $response->getHeaders().
Тело ответа.
Было $response->body. Стало (string)$response->getContents().
В тело ответа теперь приходит не строка, а поток - объект класса Laminas\Diactoros\Stream. Поэтому его нужно привести к строке (если это json, к примеру): (string)$response->getContents(). Чаще всего в коде Joomla встречается именно такой вариант. Однако, есть и вариант с перемещением указателя чтения на начало потока:
// Получили ответ в виде потока
$stream = $response->getBody();
// "перемотали" на начало
$stream->rewind();
// Получили строковый ответ
$json = $stream->getContents();
HyperFlow 1.2 — это обновлённая версия фирменного движка, разработанного с акцентом на безопасность, защиту данных и устойчивость к взлому. В новой версии реализованы современные механизмы защиты, соответствующие стандартам OWASP и требованиям к безопасной разработке.
Если вы ищете надёжный движок для сайта, защищённую CMS или систему управления с повышенной безопасностью, HyperFlow 1.2 — это решение, которому можно доверять.
Как триггерить события для плагинов на манер Joomla 5+?
В Joomla 6 должны удалить метод triggerEvent(), с помощью которого раньше вызывались события для плагинов. Теперь чтобы в своём коде вызвать событие для плагина и получить от него результаты нужно:
создать объект класса события
передать в него именованные параметры
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
// Грузим плагины нужных групп
PluginHelper::importPlugin('system');
// Создаём объект события
$event = AbstractEvent::create('onAfterInitUniverse', [
'subject' => $this,
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);
// Триггерим событие
Factory::getApplication()->getDispatcher()->dispatch(
$event->getName(), // Тут можно строку передать 'onAfterInitUniverse'
$event
);
// Получаем результаты
// В случае с AbstractEvent это может быть не 'result',
// а что-то ещё - куда сами отдадите данные.
// 2-й аргумент - значение по умолчанию,
// если не получены результаты
$results = $event->getArgument('result', []);
Плюсы такого подхода - вам не нужно запоминать порядок аргументов и проверять их наличие. Если вы написали свой класс события, то в плагине можно получать аргументы с помощью методов $event->getArticle(), $event->getData(), $event->getProduct() и подобными - реализуете сами под свои нужды.
Если такой класс события написали, то создаёте экземпляр своего класса события и укажите его явно в аргументе eventClass
use Joomla\Component\MyComponent\Administrator\Event\MyCoolEvent;
$event = MyCoolEvent::create('onAfterInitUniverse', [
'subject' => $this,
'eventClass' => MyCoolEvent::class, // ваш класс события
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);
Ожидаемо, что класс вашего события будет расширять AbsractEvent или другие классы событий Joomla.
🙁 Есть неприятный нюанс - нельзя просто так вызывать событие и ничего не передать в аргументы. Аргумент subject обязательный. Но если вы всё-таки не хотите туда ничего передавать - передайте туда пустой stdClass или объект Joomla\registry\Registry.
Раскопал интересный тип поля в Joomla - Groupedlist.
В процессе работы над компонентом нужно разделить опции выпадающего списка на группы. Я писал ранее как это сделать просто в коде тут: статья, пост.
Но как сделать такой список для использования в описаниях форм в xml? Первой мыслью было сделать свой тип поля, расширяющий стандартный \Joomla\CMS\Form\Field\ListField. Однако, в ядре Joomla нашёлся уже готовый класс поля для группированных списков \Joomla\CMS\Form\Field\GroupedlistField. Он расширяет напрямую FormField и имеет 2 метода - getGroups() и getInput().
В getInput() вызывается метод getGroups() для получения массивов с группами опций и его можно было спокойно заменить на getcollectLayoutData(), где этой работе самое и место, но это не слишком принципиально. И там и там работа делается. Поэтому нас интересует именно метод getGroups().
Мы создаём свой класс поля, расширяем GroupedlistField. Делаем обязательно свой $type для поля и реализуем метод getGroups(). Всё.
<?php
use Joomla\CMS\Form\Field\GroupedlistField;
use Joomla\CMS\HTML\HTMLHelper;
class ServerschemelistField extends GroupedlistField
{
// type совпадает с именем файла и класса
// без суффикса 'Field'
protected $type = 'Serverschemelist';
/**
* Method to get the field options.
*
* @return array The field option objects.
*
* @throws Exception
*
* @since 1.0.0
*/
protected function getGroups(): array
{
// наши группы
$group1 = [];
$group2 = [];
// Собираем первую группу опций
foreach ($data as $item) {
$optionattr = [];
// Атрибуты для <option>
if ($something_happend) {
$optionattr['option.attr'] = [
'selected' => 'selected',
'onclick' => 'earthQuake()',
'showon' => 'field1:value1000',
];
}
$group1[] = HTMLHelper::_(
'select.option',
$item->option_value,
$item->option_label_text,
$optionattr
);
}
// Аналогично собираем $group2
// ...
$groups = [
['Имя группы 1'] = $group1,
['Имя группы 2'] = $group2,
];
// В parent::getGroups() будут значения
// из xml-описания формы, если они есть.
// Соединяем их с нашими.
return array_merge(parent::getGroups(), $groups);
}
}
Many-Notes: Простые заметки в Markdown на своем сервере
Наткнулся на Reddit на небольшой, но очень интересный проект для тех, кто любит полный контроль над своими данными и ценит минимализм. Это self-hosted приложение для заметок Many-Notes.
TL;DR: Коротко о главном
Что это? Опенсорсное web-приложение для работы с Markdown-записями, спроектированное с акцентом на минимализм и полный контроль над данными. Вы разворачиваете его у себя (self-hosted).
Главная фишка: Использует базу данных (SQLite по умолчанию, но поддерживается MariaDB, MySQL и PostgreSQL) для продвинутых функций вроде многопользовательности и быстрого поиска, но при этом все заметки физически лежат в виде .md файлов. База нужна не для хранения текста заметок, а для метаданных, пользователей и индексации поиска.
Технологии: Написано на PHP, рассчитано на простую установку через Docker.
Кому зайдет? Небольшим командам или продвинутым пользователям, которым нужна своя база знаний с совместной работой, но без привязки к конкретному сервису.
Что под капотом? Ключевые возможности:
Это не просто минималистичный блокнот - внутри полноценные инструменты для командной работы. Функциональность здесь серьезная:
Многопользовательский режим и совместная работа: Можно заводить отдельных пользователей и давать им доступ к «хранилищам» (vaults). Это выводит инструмент из категории «личный блокнот» в категорию «командная база знаний».
OAuth-авторизация: Поддерживается вход через GitHub, Google, Keycloak и другие популярные сервисы.
Продвинутый редактор: Markdown + визуальный интерфейс (WYSIWYG), со сплит-панелью предпросмотра. Есть шаблоны, теги, поиск по обратным ссылкам, автосохранение.
Быстрый поиск: Используется typesense для быстрого и отказоустойчивого поиска по заметкам. Но это отдельный сервис, его тоже нужно поднять.
PWA (Progressive Web App): Приложение можно установить на рабочий стол или смартфон для более удобного доступа.
Над CMS Joomla постоянно ведётся работа: создаётся новый функционал, исправляются ошибки, делаются мелкие правки. Разработка ведётся на GitHub. Изменения оформляются в виде Pull Request (PR). Для того, чтобы изменения могли войти в ядро - их обязательно должны успешно протестировать минимум 2 человека КРОМЕ автора изменений. А помочь с большинством PR можно очень и очень быстро, это не занимает много времени, чему подтверждением служит это видео.
Сильно ждем того, кто готов быть активным участником всего процесса разработки: начиная от проектирования и заканчивая запуском и поддержкой. Того, кто не боится участвовать в обсуждении идей и заниматься исследовательской деятельностью. Того, кто может продвигать свои и чужие идеи и добиваться их реализации. Кто понимает, что важно не только писать новый код, но и поддерживать старый.
Зарплатную вилку, требования и обязанности оставили на странице вакансии — откликайтесь, если хотите попасть в команду, или отправляйте вакансию друзьям, которые ищут работу.
Привет Хабр! Это мой первый пост, и я просто хотелось спросить, стоит ли уходить в Go? У меня есть небольшая база в программировании, делал сайты на реакт и ларавел, реализовывал бэкенд с Солид и паттернами, писал на нативном пхп файловые обменники и апи. Не много знаю базы данных соответственно, гит, докер. Сейчас засматриваюсь на Go, где то вычитал что мол крутая штука для бигтехов в России, а сам я студент и пока сижу на шее у родителей, но в следующем году я окончу к курс, и хочу где то месяца за 4-5 изучить все нужное в го и во всех других сопутствующих технологиях для разработки высоконагруженных приложений и микросервисов и всякого подобного. Стоит ли сворачивать на этот путь, или добить стек ларавел плюс вью? Немного боюсь, так как слышал что в го нужны уже 25 летние синьоры со стажем работы минимум в 20 лет, но и не хочется проторчать всю жизнь в челябинской галере на фуллстеке за 70 деревянных на руки.
Это большая тема, о которой можно говорить очень много. Самое главное, что возможности применения ограничиваются только вашей больной фантазией. Вы строите интерфейс своего модуля или плагина и вам нужно подтянуть данные из сторонней системы (список чего-нибудь по какому-нибудь API), чтобы сохранить выбранный id в Joomla. Или сделать какую-то проверку и в зависимости от неё показать то или иное сообщение пользователю. Для этого подойдут свои пользовательские типы полей.
Интерфейс Joomla по большей части описан в XML-файлах. У каждого из них свои параметры. Некоторые не описаны в документации (manual.joomla.org), поэтому самым любопытным будет полезно заглянуть в собственно файлы фреймворка по пути libraries/src/Form/FormField.php, а так же в libraries/src/Form/Fields. У каждого класса поля перечислены его специфические свойства, которые можно описывать в XML. А в своём типе поля вы можете устанавливать эти значения программно.
В моём модуле WT Quick links под капотом происходят изменения. Теперь для работы (в админке) ему нужен вспомогательный плагин. А в самом модуле нам бы проверить, а не выключен ли он?
В Joomla есть тип поля Note - заметка. Его можно использовать для вывода примечаний.
<field type="note"
name="your_note_for_user"
label="Заголовок примечания"
title="Альтернативный способ для заголовка"
description="Текст примечания"
class="col-12 alert alert-info"
heading="h1"
close="true"
/>
heading- указывать уровень заголовка. close - позволяет закрыть это примечание.
В классе поля libraries/src/Form/Field/NoteField.php описана логика вывода. И в принципе оно нам подходит для нашей задачи. Но оно будет выводить сообщение всегда, а нам нужно только тогда, когда плагин отключён.
Поэтому берём и создаём свой класс поля, который мы унаследуем от NoteField. Это значит, что у нас в руках будет весь инструментарий стандартного поля Note + то, что мы сами добавим.
addfieldprefix - указываем namespace к нашему классу, может быть любой нам нужный
name - нельзя полю без имени...
Это означает, что Joomla будет использовать класс поля из файла modules/mod_wt_quick_links/src/Fields/SystempluginstatusField.php. А в классе поля будет написано следующее:
<?php
// namespace для атрибута addfieldprefix
namespace Joomla\Module\Wtquicklinks\Site\Fields;
// нельзя напрямую обращаться к этому файлу
defined('_JEXEC') or die;
// подключаем родительский класс для переопределения
use Joomla\CMS\Form\Field\NoteField;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
// имя класса и имя файла точь-в-точь
class SystempluginstatusField extends NoteField
{
protected $type = 'Systempluginstatus'; // тип поля без "Field" в конце
protected function getLabel()
{
// если плагин не включён
if(PluginHelper::isEnabled('system','wtquicklinks')) {
// меняем свойства родительского класса поля
$this->class = 'alert alert-danger w-100';
$this->element['label'] = '⚠️ А-а-а-а!';
$this->element['description'] = 'Плагин не включён!!';
// и просто рендерим его с нашими свойствами
return parent::getLabel();
}
// А иначе всё хорошо, скрываем поле из виду.
$this->parentclass = 'd-none';
return '';
}
}
Просто и удобно. И людям приятно, что о них позаботились и рассказали почему что-то не работает.
Свой класс события для плагинов Joomla. Продолжение.
Продолжение потому, что начало уже было в статье Виталия Некрасова на Хабре.
Кратко.
В Joomla 5+ для событий аргументы упаковываются в собственные классы событий: ContentPrepareEvent, AfterSaveEvent и т.д. Данные из них мы получаем в виде $event->getArgument('argument_name') или [$var, $var2] = array_values($event->getArguments());. Также для разных типов событий могут быть специфичные методы типа $article = $event->getItem(); в ContentPrepareEvent и т.д. И в статье Виталия как раз об этом рассказывается.
А так же рассказывается о методах onGet и onSet. В ядре Joomla в классе \Joomla\CMS\Event\AbstractEvent сказано:
/**
* Add argument to event.
* It will use a pre-processing method if one exists. The method has the signature:
*
* onSet($value): mixed
*
* where:
*
* $value is the value being set by the user
* It returns the value to return to set in the $arguments array of the event.
*
* @param string $name Argument name.
* @param mixed $value Value.
*
* @return $this
*
* @since 4.0.0
*/
Добрался я тоже до своего класса события для плагинов, порылся в ядре и подумал, что onSet... и onGet... методы не обязательно делать (хотя в статье по ссылке об этом не упоминается). Это методы для "предварительных проверок и манипуляций" с данными перед тем, как они будут отданы через getArgument() или get<ArgumentName>. Метод getData() отдаст данные, которые предварительно будут обработаны методом onGetData(). Но обработаны они будут только в том случае, если метод реализован. Если нет, то ничего страшного. Ошибки не будет.😎
Эти методы напоминают своеобразные плагины внутри плагинов. На мой взгляд излишнее усложнение, хотя сеттеры и геттеры должны заниматься по идее только сеттерством и геттерством, а проверку/ приведение типов можно отдать в методы onSet... / onGet....
Опубликовано исследование о том что индексирование сайтов поисковиком (Google) не зависит от того, SPA ли это или же он SSR. Также пару лет назад делал аналогичное расследование и пришел к тому же выводу.
Вообще, мы пришли к идеалу достаточно давно - когда сервер занимается своими делами, а клиент статический, минифицирован, и раздается из CDN для быстроты и без траты ресурсов сервера.
Автоматическое подключение локализации для веб-ассета в Joomla
Начиная с Joomla 4 в ядре реализована концепция веб-ассетов. Управление JavaScript и CSS в Joomla значительно упростилось благодаря классу WebAssetManager. Есть замечательная статья Как правильно подключать JavaScript и CSS в Joomla 4, в которой подробно и с примерами кода рассказывается об этой концепции и её применении. Например, в web asset мы можем оформить какую-нибудь готовую js-карусель или библиотеку.
Также можно оформить веб-ассетом и свой собственный js-скрипт, которому могут понадобиться дополнительные данные для работы на странице: как данные из PHP, так и языковые константы. С помощью WebAssetManager мы можем получить эти данные в момент сразу при подключении ассета. Как это сделать?
Для веб ассетов в Joomla создаётся файл joomla.asset.json, в котором описываются url подключаемых файлов, версии, их зависимости друг от друга, собираются пресеты для подключения пачкой и т.д. В нём можно указать пользовательский класс WebAssetItem, который будет выполнять нужную работу для вашего ассета. Для этого определите свойства namespace и class для всего файла или же для каждого ассета.
Ассет foo будет работать с классом Joomla\Component\Example\Administrator\WebAsset\FooAssetItem, а ассет bar с классом MyFooBar\Library\Example\WebAsset\BarAssetItem. Если namespace не указан, будет использоваться Joomla\CMS\WebAsset по умолчанию. Ну и сам класс должен находиться по указанному неймспейсу.
<?php
/**
* Класс WebAssetItem для подключения данных для работы веб ассета
*/
namespace Joomla\Component\Example\Administrator\WebAsset\AssetItem;
\defined('_JEXEC') or die;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\WebAsset\WebAssetAttachBehaviorInterface;
use Joomla\CMS\WebAsset\WebAssetItem;
class FooAssetItem extends WebAssetItem implements WebAssetAttachBehaviorInterface
{
/**
* Method called when asset attached to the Document.
*
* @param Document $doc Active document
*
* @throws \Exception
*
* @since 1.0.0
*/
public function onAttachCallback(Document $doc)
{
Factory::getApplication()->getLanguage()->load('com_example');
// Add my-js-script.js language strings
Text::script('COM_EXAMPLE_LANGUAGE_STRING_FOR_FRONTEND');
/** @var array $data Данные для фронтенда, чтобы получать их
* в js через Joomla.getOptions('com_example.foo.js.data';)
*/
$data = [
'any' => 'data',
];
/** @var bool $merge Whether merge with existing (true) or replace (false) */
$merge = true;
$doc->addScriptOptions('com_example.foo.js.data', $data, $merge);
}
}
Таким образом для нашего js-скрипта мы получили и локализованные стринги сообщений (как? - пост на Хабре) и дополнительные данные из PHP для фронтенда (статья на Хабре - в середине). Теперь когда вы где-то в любом месте Joomla подключаете веб ассет с помощью $wa->useScript('foo') - автоматически подключится всё необходимое для его работы.
Совет по Joomla: dot-нотация для доступа к значениям вложенных массивов.
Позволю себе немного ребячества ))
Наткнулся на пост в одном из php-шных каналов о том, как в Laravel можно использовать нотацию "точка" для доступа к значениям вложенных массивов. И тем самым упростить доступ к многомерным массивам с помощью одной строки, разделенной точками.