Помощник модуля
Помощник (Helper) — класс, в который выносят получение данных: запрос к базе, обращение к внешнему сервису, расчёты. Диспетчер остаётся коротким: он только просит данные у помощника и передаёт их макету. Научим модуль mod_hello показывать последние статьи сайта.
Где лежит
Создайте вручную папку src/Helper и файл в ней:
modules/mod_hello/
├── mod_hello.xml
├── services/provider.php
├── src/
│ ├── Dispatcher/Dispatcher.php
│ └── Helper/
│ └── HelloHelper.php новый файл
└── tmpl/default.phpМанифест менять не нужно: папка src в нём уже указана целиком.
Класс помощника
// modules/mod_hello/src/Helper/HelloHelper.php
namespace My\Module\Hello\Site\Helper;
defined('_JEXEC') or die;
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;
class HelloHelper implements DatabaseAwareInterface
{
use DatabaseAwareTrait;
public function getArticles(int $limit): array
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select($db->quoteName(['id', 'title', 'catid', 'language']))
->from($db->quoteName('#__content'))
->where($db->quoteName('state') . ' = 1')
->order($db->quoteName('created') . ' DESC')
->setLimit($limit);
return $db->setQuery($query)->loadObjectList();
}
}Метод возвращает массив объектов — последние опубликованные статьи. Интерфейс DatabaseAwareInterface говорит Joomla: «этому классу нужна база», и она сама передаёт подключение; getDatabase() его возвращает. Запросы подробно разобраны в главе о компоненте.
Вызов из диспетчера
Помощника получают через фабрику — ту самую, что зарегистрирована в провайдере строкой HelperFactory:
// modules/mod_hello/src/Dispatcher/Dispatcher.php
namespace My\Module\Hello\Site\Dispatcher;
defined('_JEXEC') or die;
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
{
use HelperFactoryAwareTrait;
protected function getLayoutData(): array
{
$data = parent::getLayoutData();
$data['greeting'] = 'Привет!';
$data['articles'] = $this->getHelperFactory()
->getHelper('HelloHelper')
->getArticles(5);
return $data;
}
}getHelper('HelloHelper') создаёт объект класса из папки src/Helper. В макет уходит новая переменная $articles.
Вывод в макете
<?php
// modules/mod_hello/tmpl/default.php
defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
use Joomla\Component\Content\Site\Helper\RouteHelper;
?>
<div class="mod-hello">
<p><?php echo htmlspecialchars($greeting, ENT_QUOTES, 'UTF-8'); ?></p>
<ul>
<?php foreach ($articles as $article) : ?>
<li>
<a href="<?php echo Route::_(RouteHelper::getArticleRoute($article->id, $article->catid, $article->language)); ?>">
<?php echo htmlspecialchars($article->title, ENT_QUOTES, 'UTF-8'); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>Обновите страницу сайта: под приветствием появился список из пяти последних статей со ссылками. RouteHelper::getArticleRoute() — готовый метод компонента статей, который собирает адрес статьи, а Route::_() превращает его в понятный адрес.
Что ещё есть в данных
Родительский getLayoutData() уже кладёт в массив несколько значений:
| Переменная в макете | Что в ней |
|---|---|
$module | Сам модуль: $module->title, $module->position |
$params | Настройки модуля |
$app | Приложение Joomla |
$input | Данные запроса |
Частая ошибка
Запрос к базе пишут прямо в макете tmpl/default.php. Работать будет, но макет перестаёт быть просто разметкой: владелец сайта, переопределив его в шаблоне, получит копию запроса и сломает модуль при первом обновлении. Данные готовит помощник, макет только выводит.