To use J4 style or custom naming conventions with AJAX you have to convert the module to new service-based format. At a minimum, service provider (
services/provider.php) needs to provide a module extension, a dispatcher factory and a helper factory:
defined('_JEXEC') or exit;
return new class implements ServiceProviderInterface
public function register(Container $container)
mod_articles_latest.php entry file is replaced by a dispatcher class. Default dispatcher factory constructs the class this way:
[Base Namespace]\[Application Name]\Dispatcher\Dispatcher
So with the above example namespace the class would be this:
You can use custom naming conventions, as well as inject dependencies by creating your own implementation of
For the dispatcher you can extend
Joomla\CMS\Dispatcher\AbstractModuleDispatcher or create your own implementation of
Joomla\CMS\Dispatcher\DispatcherInterface. The dispatcher should fetch the data and render the module layout. If extending the abstract dispatcher, override
getLayoutData() method to add the data you need. Strangely, neither the module extension instance, nor the helper is available in the dispatcher. You have to boot the module through application:
\defined('_JEXEC') or die;
class Dispatcher extends AbstractModuleDispatcher
protected function getLayoutData()
// Gets some common data like application instance, module instance, module params, etc.
$data = parent::getLayoutData();
// Gets the module helper.
$helper = $this->app->bootModule('mod_articles_latest', 'Site')->getHelper('ArticlesLatestHelper');
$model = $this->app->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Site', ['ignore_request' => true]);
// Data array will be extracted to variables, i.e. this will be accessible as $list in the layout.
$data['list'] = $helper->getList($data['params'], $model);
Helper's class name is built simply from the namespace defined in helper factory plus the class name passed its
getHelper() method. In this example, the class would be
Joomla\Module\ArticlesLatest\Site\Helper\ArticlesLatestHelper. For custom naming conventions you could create your own implementation of
Joomla\CMS\Helper\HelperFactoryInterface. Except that not really because
com_ajax expects helper to be named in certain way. For this module
com_ajax would always pass
getHelper() method. So your custom factory would still need to be aware of this format. This was a really bad decision by the developers which partly beats the purpose of having such factory in the first place... This would have been better off with AJAX-specific interface.
Finally, some changes might be needed for the helper. Helpers must be instantiable, meaning they must not be abstract and must have public constructors (not necessary if using custom factory, e.g. which could call a
getInstance() method on the helper). This is in contrast to J3 helpers which were entirely static (at least in core modules).