Создание модуля для Joomla под ключ
Мы разрабатываем кастомные модули Joomla с нуля. Недавно столкнулись с задачей: вывести на главной странице интернет-магазина блок "хиты продаж" с фильтрацией по категории и кэшированием. Готовые решения не подходили — тянули лишние стили, плодили N+1 запросы. Написали свой модуль за два дня. Расскажем, как это делаем.
Кастомный модуль Joomla — это не просто виджет. Это полностью контролируемый элемент на своей позиции шаблона. Он может отображать данные из любых таблиц, внешних API или вычислять значения на лету. Примеры: последние новости, форма обратной связи, статистика посещений, курсы валют, рекомендации товаров. Главное — он не тормозит сайт и не конфликтует с другими расширениями. Как заявляют разработчики Joomla в руководстве по разработке модулей Joomla, кастомные модули являются основой для гибкой архитектуры.
В этой статье разберём на реальном примере: модуль вывода выделенных товаров каталога. Покажем структуру, манифест, helper с кэшированием, dispatcher и шаблон. А главное — как избежать типичных ошибок: дублирование запросов, отсутствие кэширования, несовместимость с Joomla 5.
Почему кастомный модуль Joomla лучше готового компонента?
Готовые модули из маркетплейса часто перегружены опциями, которые не нужны вашему проекту. Они могут конфликтовать с другими расширениями, требовать дополнительных библиотек и замедлять страницу. Кастомный модуль содержит ровно тот код, который нужен под задачу. Вы контролируете каждый SQL-запрос, каждый шаблон и каждую настройку. В итоге — минимальное время загрузки (LCP < 2.5 с) и отсутствие лишних HTTP-запросов. Например, в одном проекте мы сэкономили заказчику на хостинге за счёт оптимизации запросов и кэширования.
Когда нужен кастомный модуль Joomla?
Кастомный модуль оправдан, когда стандартных решений недостаточно: требуется интеграция со сторонним API, вывод данных из нестандартных таблиц, сложная логика фильтрации или кэширование, которое не поддерживается готовыми модулями. Также он незаменим, если важна максимальная производительность и минимальный размер кода. Стоимость разработки рассчитывается индивидуально, но вложения быстро окупаются за счёт экономии ресурсов сервера и времени на поддержку.
Как реализовать кэширование в модуле Joomla?
Кэширование — это ключевой момент для производительности. В нашем helper мы используем встроенный Cache API Joomla: оборачиваем запрос к БД в кэш с временем жизни 15 минут. Это снижает нагрузку на сервер и ускоряет загрузку страницы для пользователя.
Устройство модуля Joomla
Стандартный кастомный модуль включает следующие файлы:
-
mod_product_highlights.php— точка входа -
mod_product_highlights.xml— манифест -
src/Dispatcher/Dispatcher.php— диспетчер -
src/Helper/ProductHighlightsHelper.php— хелпер -
tmpl/default.php— шаблон -
language/ru-RU/...— языковые файлы
Манифест
Пример манифеста
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" client="site" version="4.0">
<name>mod_product_highlights</name>
<author>Your Company</author>
<version>1.0.0</version>
<description>Выделенные товары каталога</description>
<namespace path="src">MyCompany\Module\ProductHighlights</namespace>
<files>
<filename module="mod_product_highlights">mod_product_highlights.php</filename>
<folder>src</folder>
<folder>tmpl</folder>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field name="count" type="number" label="Количество товаров"
default="4" min="1" max="12" />
<field name="category_id" type="sql"
label="Категория"
query="SELECT id AS value, title AS text FROM #__catalog_categories WHERE published = 1"
default="" />
<field name="show_price" type="radio" label="Показать цену" default="1">
<option value="1">Да</option>
<option value="0">Нет</option>
</field>
</fieldset>
</fields>
</config>
</extension>
Helper с кэшированием
Пример Helper с кэшированием
// src/Helper/ProductHighlightsHelper.php
namespace MyCompany\Module\ProductHighlights\Site\Helper;
use Joomla\CMS\Factory;
class ProductHighlightsHelper {
public static function getProducts(object $params): array {
$cache = Factory::getCache('mod_product_highlights', 'callback');
$cache->setCaching(true);
$cache->setLifeTime(15); // минут
$cacheId = md5('product_highlights_' . json_encode($params));
return $cache->get([static::class, '_fetchProducts'], [$params], $cacheId) ?: [];
}
public static function _fetchProducts(object $params): array {
$db = Factory::getDbo();
$count = (int) $params->get('count', 4);
$catId = (int) $params->get('category_id', 0);
$query = $db->getQuery(true)
->select(['id', 'title', 'price', 'image', 'alias'])
->from($db->quoteName('#__catalog_products'))
->where($db->quoteName('published') . ' = 1')
->where($db->quoteName('featured') . ' = 1');
if ($catId) {
$query->where($db->quoteName('category_id') . ' = ' . $catId);
}
$query->order('ordering ASC')->setLimit($count);
$db->setQuery($query);
return $db->loadObjectList() ?: [];
}
}
Dispatcher
// src/Dispatcher/Dispatcher.php
namespace MyCompany\Module\ProductHighlights\Site\Dispatcher;
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
use MyCompany\Module\ProductHighlights\Site\Helper\ProductHighlightsHelper;
class Dispatcher extends AbstractModuleDispatcher {
protected function getLayoutData(): array {
$data = parent::getLayoutData();
$products = ProductHighlightsHelper::getProducts($data['params']);
$data['products'] = $products;
$data['showPrice'] = (bool) $data['params']->get('show_price', true);
return $data;
}
}
Шаблон
// tmpl/default.php
defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
?>
<div class="mod-product-highlights">
<?php foreach ($products as $product) : ?>
<div class="product-card">
<?php if ($product->image) : ?>
<img src="<?php echo $product->image; ?>"
alt="<?php echo htmlspecialchars($product->title); ?>"
loading="lazy">
<?php endif; ?>
<h4 class="product-card__title">
<a href="<?php echo Route::_('index.php?option=com_catalog&view=product&alias=' . $product->alias); ?>">
<?php echo htmlspecialchars($product->title); ?>
</a>
</h4>
<?php if ($showPrice && $product->price) : ?>
<p class="product-card__price"><?php echo number_format($product->price, 0, '.', ' '); ?> ₽</p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
Мы уделяем внимание alt-атрибутам: для изображения товара в модуле задаём alt, соответствующий названию товара. Это улучшает доступность и SEO.
Процесс работы
| Этап | Длительность |
|---|---|
| Анализ и спецификация | 1 день |
| Разработка кода | 1–2 дня |
| Тестирование и отладка | 1 день |
| Интеграция в проект | 0,5 дня |
| Итого | 3–5 дней |
Сравнение кастомного модуля и готового плагина
| Параметр | Кастомный модуль | Готовый плагин |
|---|---|---|
| Гибкость | Полная (любая логика) | Ограничена настройками |
| Размер | Только нужный код (~10–20 КБ) | Часто 1–5 МБ с библиотеками |
| Производительность | Оптимизирован под задачу | Может тормозить из‑за лишних запросов |
| Зависимости | Нет | Может требовать другие расширения |
| Поддержка версий Joomla | Адаптируем под 4 и 5 | Не всегда обновляется |
Что входит в работу
- Готовый модуль с манифестом, helper, dispatcher, шаблоном и языковыми файлами.
- Настройка кэширования для снижения нагрузки на БД.
- Документация по установке и настройке.
- Консультация по размещению в нужной позиции шаблона.
- Поддержка в течение 30 дней после сдачи.
Сроки и стоимость
Разработка кастомного модуля занимает от 3 до 5 дней в зависимости от сложности. Стоимость рассчитывается индивидуально. Мы гарантируем совместимость с Joomla 4 и 5, а также отсутствие ошибок в коде.
Мы накопили многолетний опыт в оптимизации запросов, кэшировании и создании удобных интерфейсов для администраторов. Получите предварительный расчёт за 1 день — отправьте задачу. Закажите разработку модуля Joomla и получите готовый код с гарантией.
Свяжитесь с нами для обсуждения вашей задачи — мы поможем реализовать функционал, который идеально впишется в ваш проект.







