Створення модуля для 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 та отримайте готовий код з гарантією.
Зв'яжіться з нами для обговорення вашого завдання — ми допоможемо реалізувати функціонал, який ідеально впишеться у ваш проект.







