As with all native extensions since Joomla 4, modules have a service
provider named provider.php
in their
services
directory. The purpose of this provide is to
tell Joomla where to find the module's dispatcher, and register the
module's helper as a service.
It's just a bit of boilerplate code, like this:
<?php defined('_JEXEC') || die; use Joomla\CMS\Extension\Service\Provider\HelperFactory; use Joomla\CMS\Extension\Service\Provider\Module; use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; return new class () implements ServiceProviderInterface { public function register(Container $container) { $container->registerServiceProvider(new ModuleDispatcherFactory('\\Acme\\Module\\Example')); $container->registerServiceProvider(new HelperFactory('\\Acme\\Module\\Example\\Site\\Helper')); $container->registerServiceProvider(new Module()); } };
There are really two things you need to take note of here.
The argument to the
Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory
's
constructor is the namespace of the module without the Site or
Administrator part. In other words, it is exactly what you put in your XML
manifest. Joomla knows to add the Site (frontend modules) or Administrator
(backend modules) to the namespace, and look for
Dispatcher\Dispatcher
under it. In other words, in
the example frontend module we have here, the Dispatcher class is
understood to be
Acme\Module\Example\Site\Dispatcher\Dispatcher
.
![]() | Tip |
---|---|
Remember! A module always needs a Dispatcher. This is where you tell Joomla what data to send to the module's view template for display. If you were to not implement a Dispatcher you would have nothing useful to display. This is the big change from Joomla 3.x and earlier. It is no longer possible to pull data in the view template from the module helper directly. It is always pushed to the module. |
The argument to the
Joomla\CMS\Extension\Service\Provider\HelperFactory
's
constructor, however, is a fully qualified namespace to the module's
Helper classes. This means that it's the namespace you put in your XML
manifest, plus Site (frontend modules) or Administrator, plus Helper. In
other words, in the example frontend module we have here, the helper
classes' namespace is
Acme\Module\Example\Site\Helper
.
The HelperFactory does a modicum of "magic" when instantiating your
helper classes. It checks which interfaces they implement and pushes the
respective services to them. At the time of this writing, it checks if the
helper class implements the
Joomla\Database\DatabaseAwareInterface
interface and pushes the database object to the instantiated helper object
using the interface's setDatabase
method.
If you want to push custom services to your helpers you need to
subclass the
Joomla\CMS\Extension\Service\Provider\HelperFactory
class and use your custom helper factory instead of Joomla's in your
service provider. Unfortunately, merely extending the service does not
work as expected (there's been a long discussion we've already had in the
Joomla! GitHub Issues about it).