Work In Progress

This book is currently work in progress. Some sections are not yet written. Thank you for your understanding!

Service provider

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]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).