Версия: Joomla 5.4.5 — это релиз из серии 5.4.x, выпущенный в апреле 2026 года как исправление ошибок. Структура и соглашения, описанные здесь, применимы ко всем версиям Joomla 5.4.x.
Разработка компонентов в Joomla 5 следует архитектуре MVC (модель-представление-контроллер), но организация файлов принципиально отличается от Joomla 3: пространства имён — это ядро системы, пути и имена классов должны строго соответствовать друг другу, а ошибки в регистре на Linux приводят к тому, что класс не находится. Это руководство описывает все файлы и соглашения, необходимые для минимального работающего компонента, а в конце приведён готовый промпт для aider, который автоматизирует сборку установочного пакета.
1. Выбор пути разработки
Создать компонент Joomla 5 можно несколькими способами. Самый надёжный — вручную собрать минимальную структуру: без внешних генераторов и Node.js, вы полностью контролируете каждый файл. Альтернатива — Joomla Component Builder (JCB), графический генератор компонентов, устанавливаемый в Joomla, подходящий для быстрого создания CRUD. Есть также официальный туториал Joomla, шаг за шагом ведущий к полному компоненту. Для понимания внутренних механизмов Joomla 5 ручная сборка минимальной структуры — лучшая отправная точка.
2. Структура установочного пакета
Компонент Joomla должен быть упакован в .zip-архив, содержащий как минимум два каталога верхнего уровня: site/ (фронтенд) и admin/ (бэкенд). При установке Joomla копирует содержимое site/ в /components/com_имя, а admin/ — в /administrator/components/com_имя.
Дерево минимального компонента:
com_example/
├── example.xml # манифест
├── admin/
│ ├── services/
│ │ └── provider.php # регистрация в DI-контейнере
│ ├── src/
│ │ ├── Extension/
│ │ │ └── ExampleComponent.php # класс компонента
│ │ ├── Controller/
│ │ │ └── DisplayController.php # контроллер по умолчанию
│ │ └── View/
│ │ └── Example/
│ │ └── HtmlView.php # представление
│ ├── tmpl/
│ │ └── example/
│ │ └── default.php # шаблон
│ └── language/
│ └── en-GB/
│ ├── com_example.ini
│ └── com_example.sys.ini
└── site/
├── src/
│ ├── Controller/
│ │ └── DisplayController.php
│ └── View/
│ └── Example/
│ └── HtmlView.php
├── tmpl/
│ └── example/
│ └── default.php
└── language/
└── en-GB/
└── com_example.ini
3. Манифест (Manifest)
Манифест сообщает Joomla: это компонент, вот его пространство имён, вот где лежат файлы. Ключевые элементы:
<extension type="component" method="upgrade">
<name>example</name>
<namespace path="src">MyCompany\Component\Example</namespace>
<administration>
<menu>COM_EXAMPLE</menu>
<files folder="admin">
<folder>services</folder>
<folder>src</folder>
<folder>tmpl</folder>
<folder>language</folder>
</files>
</administration>
<files folder="site">
<folder>src</folder>
<folder>tmpl</folder>
<folder>language</folder>
</files>
</extension>
Ключевой момент: значение <name> должно совпадать с именем компонента (без префикса com_) и обычно записывается в нижнем регистре. Если <name> в манифесте не совпадает с тем, что ожидает Joomla, может возникнуть ошибка «Invalid controller class: display». Атрибут path="src" в <namespace> указывает, что файлы классов лежат в подкаталоге src/ корня компонента; Joomla автоматически сгенерирует префиксы пространств имён \...\Administrator и \...\Site для бэкенда и фронтенда.
4. Соответствие пространств имён и путей
Joomla 5 использует PSR-4 автозагрузку. По префиксу пространства имён Joomla определяет каталог:
MyCompany\Component\Example\Administrator\→administrator/components/com_example/src/MyCompany\Component\Example\Site\→components/com_example/src/
Это означает, что класс MyCompany\Component\Example\Administrator\Controller\DisplayController должен находиться в файле administrator/components/com_example/src/Controller/DisplayController.php. Регистр имён файлов и каталогов должен точно совпадать с пространством имён. Linux различает регистр: DisplayController.php и displaycontroller.php — разные файлы, и Joomla будет искать только первый.
5. Сервис-провайдер (provider.php)
admin/services/provider.php — мост между компонентом и DI-контейнером Joomla. Он регистрирует две фабрики: ComponentDispatcherFactory (создаёт диспетчер, а затем контроллеры) и MVCFactory (создаёт модели, представления, таблицы).
<?php
\defined('_JEXEC') or die;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
return new class implements ServiceProviderInterface
{
public function register(Container $container)
{
$namespace = '\\MyCompany\\Component\\Example';
$container->registerServiceProvider(new ComponentDispatcherFactory($namespace));
$container->registerServiceProvider(new MVCFactory($namespace));
$container->set(
ComponentInterface::class,
function (Container $container) {
$component = new \MyCompany\Component\Example\Administrator\Extension\ExampleComponent(
$container->get(ComponentDispatcherFactoryInterface::class)
);
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
return $component;
}
);
}
};
Самая частая ошибка: добавление суффикса \\Administrator к пространству имён, передаваемому в ComponentDispatcherFactory и MVCFactory. Эти фабрики принимают корневое пространство имён (\MyCompany\Component\Example) и сами добавляют Administrator или Site в зависимости от того, откуда пришёл запрос. Лишний \\Administrator заставит фабрику искать контроллеры в Administrator\Administrator\Controller, что приведёт к ошибке «Invalid controller class: display».
6. Класс компонента (Extension)
admin/src/Extension/ExampleComponent.php — главный класс компонента. Для минимального компонента достаточно унаследоваться от MVCComponent:
<?php
namespace MyCompany\Component\Example\Administrator\Extension;
use Joomla\CMS\Extension\MVCComponent;
class ExampleComponent extends MVCComponent
{
}
MVCComponent уже предоставляет базовую функциональность, необходимую диспетчеру. Переопределять boot() или реализовывать дополнительные интерфейсы нужно только тогда, когда компоненту требуются HTML-сервисы, сервисы категорий и т.п.
7. Контроллер (DisplayController)
Контроллер по умолчанию для бэкенда — admin/src/Controller/DisplayController.php. Он наследуется от BaseController и через $default_view указывает, какое представление использовать, когда параметр view не задан:
<?php
namespace MyCompany\Component\Example\Administrator\Controller;
use Joomla\CMS\MVC\Controller\BaseController;
class DisplayController extends BaseController
{
protected $default_view = 'example';
}
Контроллер фронтенда имеет ту же структуру, только пространство имён — ...\Site\Controller. Когда URL имеет вид ?option=com_example (без параметра task), диспетчер Joomla создаёт DisplayController и вызывает его метод display() по умолчанию.
8. Представление (HtmlView)
Представление подготавливает данные и рендерит шаблон. admin/src/View/Example/HtmlView.php:
<?php
namespace MyCompany\Component\Example\Administrator\View\Example;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
class HtmlView extends BaseHtmlView
{
public function display($tpl = null)
{
$this->title = Text::_('COM_EXAMPLE_TITLE');
parent::display($tpl);
}
}
Имя класса представления должно соответствовать имени каталога и параметру view в запросе. Параметр view=example в URL заставит MVCFactory искать ...\View\Example\HtmlView.
9. Шаблон (default.php)
Шаблон — это чистый PHP/HTML-файл, расположенный в admin/tmpl/example/default.php (и в соответствующем site/tmpl/example/default.php для фронтенда):
<?php
\defined('_JEXEC') or die;
?>
<div class="container">
<h1><?php echo $this->title; ?></h1>
<p>Hello from com_example.</p>
</div>
Обратите внимание: шаблоны не находятся в src/, поэтому им не нужен namespace. \defined('_JEXEC') or die; в таких файлах без пространства имён допустим и рекомендуется.
10. Языковые файлы
Joomla выводит текст через языковые константы, а не хардкод строк. Языковые файлы бэкенда лежат в admin/language/en-GB/:
com_example.ini (используется в интерфейсе компонента):
COM_EXAMPLE_TITLE="Example Component"
COM_EXAMPLE_DESCRIPTION="A minimal Joomla 5 component."
com_example.sys.ini (используется Joomla для отображения имени и описания в менеджере расширений):
COM_EXAMPLE="Example"
COM_EXAMPLE_XML_DESCRIPTION="A minimal Joomla 5 component."
11. Ловушка с пространствами имён и defined('_JEXEC')
В PHP-файлах, содержащих объявление namespace, defined('_JEXEC') or die; не может стоять перед namespace. PHP требует, чтобы namespace был первым оператором в файле (кроме declare). Если вызвать defined() до namespace, возникнет фатальная ошибка: «Namespace declaration statement has to be the very first statement».
Правильный подход:
- Файлы классов с пространством имён (в
src/): ставьте\defined('_JEXEC') or die;послеnamespaceиuse, с обратным слешем передdefined. - Файлы шаблонов без пространства имён (в
tmpl/):defined('_JEXEC') or die;можно ставить в начале файла.
12. Установка и кэш
Упаковав структуру в com_example.zip, установите её через бэкенд Joomla: System → Install → Extensions. Joomla скопирует файлы в нужные места и зарегистрирует компонент в таблице #__extensions.
После установки Joomla обновляет administrator/cache/autoload_psr4.php, сопоставляя префикс вашего пространства имён с путём в файловой системе. Если после установки компонент выдаёт «класс не найден» или «Invalid controller class», сначала проверьте, есть ли в этом файле запись для пространства имён вашего компонента. Если нет — удалите файл и обновите страницу, Joomla пересоздаст его. Также убедитесь, что плагин «Extension - Namespace Updater» включён — он отвечает за обновление этого кэша при установке/обновлении расширений.
13. Проверка работоспособности компонента
После установки в меню Components бэкенда должен появиться ваш компонент. Нажмите на него — если вы видите заголовок, выводимый шаблоном, значит вся цепочка (манифест → установка → DI-контейнер → диспетчер → контроллер → представление → шаблон) работает. Дальше можно добавлять модели, таблицы, формы и CRUD-контроллеры, размещая каждый новый класс в правильном каталоге src/ с правильным пространством имён.
14. Частые ошибки и их причины
| Симптом | Причина |
|---|---|
| «Invalid controller class: display» | Лишний \\Administrator в ComponentDispatcherFactory/MVCFactory; несовпадение <name> в манифесте; устаревший autoload_psr4.php |
| «Namespace declaration statement has to be the very first statement» | defined('_JEXEC') стоит перед namespace в файле класса |
| «Class not found» | Регистр имени файла/каталога не совпадает с пространством имён; autoload_psr4.php не обновился |
| «Could not create directory» при установке | Нет прав на запись в components/ или administrator/components/ |
| Компонент установился, но не появился в меню | Не указан <menu> в секции <administration> манифеста |
15. Что дальше
Минимальный компонент — это фундамент. Следующие шаги: добавление модели и таблицы для работы с данными, создание форм (XML-формы в admin/src/Model/Forms/ или admin/forms/), CRUD-контроллеры, маршрутизация на фронтенде, права доступа (ACL). Каждый новый класс кладётся в соответствующий подкаталог src/ с пространством имён, соответствующим пути. Главное правило остаётся неизменным: пространство имён, путь к файлу и имя класса должны совпадать с точностью до регистра.
16. Промпт для aider: сборка установочного пакета
Когда компонент уже работает на живом сайте, его нужно упаковать в zip для повторной установки или резервной копии. Приведённый ниже промпт автоматизирует этот процесс через aider. Скопируйте его целиком в aider, запущенный из корня сайта Joomla.
Задача: создать установочный zip-пакет компонента Joomla 5.4.5 из уже работающих файлов на живом сайте.
Контекст:
- Компонент уже установлен и работает в Joomla 5.4.5.
- Корень сайта: /var/www/www-root/data/www/example.ru
- Имя компонента: com_example
- Namespace: MyCompany\Component\Example
- Рабочие файлы:
- administrator/components/com_example/ (бэкенд)
- components/com_example/ (фронтенд)
- Манифест: administrator/components/com_example/example.xml
Что нужно сделать:
1. Создать временную папку сборки:
/var/www/www-root/data/www/example.ru/tmp/build_package
2. Внутри build_package создать структуру:
build_package/
├── example.xml (копия манифеста из administrator/components/com_example/)
├── admin/ (копия содержимого administrator/components/com_example/, БЕЗ example.xml)
└── site/ (копия содержимого components/com_example/)
3. Удалить из build_package/admin/ файл example.xml, если он туда попал (манифест должен быть только в корне архива).
4. Проверить, что в build_package/example.xml:
- <name>example</name> (нижний регистр, без com_)
- <namespace path="src">MyCompany\Component\Example</namespace>
- <files folder="admin"> и <files folder="site"> присутствуют
5. Проверить, что в build_package/admin/services/provider.php:
- ComponentDispatcherFactory('\\MyCompany\\Component\\Example')
- MVCFactory('\\MyCompany\\Component\\Example')
- НЕТ суффикса \\Administrator в этих вызовах
6. Создать zip-архив:
cd /var/www/www-root/data/www/example.ru/tmp/build_package
zip -r /var/www/www-root/data/www/example.ru/tmp/com_example_package.zip .
7. Установить владельца архива:
chown www-root:www-root /var/www/www-root/data/www/example.ru/tmp/com_example_package.zip
8. Проверить архив:
unzip -l /var/www/www-root/data/www/example.ru/tmp/com_example_package.zip | head -40
unzip -p /var/www/www-root/data/www/example.ru/tmp/com_example_package.zip example.xml | grep "<name>"
Ожидаемый результат:
- В корне архива только один example.xml
- <name>example</name>
- admin/ и site/ содержат все рабочие файлы
- Архив готов к установке через Upload Package File в админке Joomla
Не делай:
- Не добавляй defined('_JEXEC') перед namespace в файлах src/
- Не меняй namespace в файлах без необходимости
- Не добавляй \\Administrator в provider.php
- Не создавай дополнительных манифестов внутри admin/
После выполнения покажи:
- Список файлов в архиве (unzip -l)
- Значение <name> из манифеста в архиве
- Размер архива
Этот промпт фиксирует все места, где чаще всего возникают ошибки при упаковке компонента Joomla 5.4.5: дубликат манифеста внутри admin/, лишний \\Administrator в provider.php, неверный регистр в <name>. Его можно использовать и как чек-лист при ручной сборке.
Автор статьи: https://jedig.ru