Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

The module helper

A helper is a class that holds data retrieval: a database query, a call to an external service, calculations. The dispatcher stays short: it only asks the helper for data and passes it to the layout. Let us teach mod_hello to show the latest articles of the site.

Where it lives

Create the src/Helper folder and a file in it by hand:

modules/mod_hello/
├── mod_hello.xml
├── services/provider.php
├── src/
│   ├── Dispatcher/Dispatcher.php
│   └── Helper/
│       └── HelloHelper.php          new file
└── tmpl/default.php

The manifest does not change: the whole src folder is already listed in it.

The helper class

// modules/mod_hello/src/Helper/HelloHelper.php
namespace My\Module\Hello\Site\Helper;
 
defined('_JEXEC') or die;
 
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;
 
class HelloHelper implements DatabaseAwareInterface
{
    use DatabaseAwareTrait;
 
    public function getArticles(int $limit): array
    {
        $db = $this->getDatabase();
 
        $query = $db->getQuery(true)
            ->select($db->quoteName(['id', 'title', 'catid', 'language']))
            ->from($db->quoteName('#__content'))
            ->where($db->quoteName('state') . ' = 1')
            ->order($db->quoteName('created') . ' DESC')
            ->setLimit($limit);
 
        return $db->setQuery($query)->loadObjectList();
    }
}

The method returns an array of objects — the latest published articles. The DatabaseAwareInterface interface tells Joomla "this class needs the database", and Joomla passes the connection in itself; getDatabase() returns it. Queries are covered in detail in the component chapter.

Calling it from the dispatcher

The helper is obtained through a factory — the one registered in the provider by the HelperFactory line:

// modules/mod_hello/src/Dispatcher/Dispatcher.php
namespace My\Module\Hello\Site\Dispatcher;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
 
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
{
    use HelperFactoryAwareTrait;
 
    protected function getLayoutData(): array
    {
        $data = parent::getLayoutData();
 
        $data['greeting'] = 'Hello!';
        $data['articles'] = $this->getHelperFactory()
            ->getHelper('HelloHelper')
            ->getArticles(5);
 
        return $data;
    }
}

getHelper('HelloHelper') creates an object of the class from the src/Helper folder. A new variable, $articles, goes to the layout.

Output in the layout

<?php
// modules/mod_hello/tmpl/default.php
 
defined('_JEXEC') or die;
 
use Joomla\CMS\Router\Route;
use Joomla\Component\Content\Site\Helper\RouteHelper;
?>
<div class="mod-hello">
    <p><?php echo htmlspecialchars($greeting, ENT_QUOTES, 'UTF-8'); ?></p>
 
    <ul>
        <?php foreach ($articles as $article) : ?>
            <li>
                <a href="<?php echo Route::_(RouteHelper::getArticleRoute($article->id, $article->catid, $article->language)); ?>">
                    <?php echo htmlspecialchars($article->title, ENT_QUOTES, 'UTF-8'); ?>
                </a>
            </li>
        <?php endforeach; ?>
    </ul>
</div>

Reload the site page: a list of the five latest articles with links appears under the greeting. RouteHelper::getArticleRoute() is a ready-made method of the articles component that builds an article address, and Route::_() turns it into a readable URL.

What else is in the data

The parent getLayoutData() already puts several values into the array:

Variable in the layoutWhat it holds
$moduleThe module itself: $module->title, $module->position
$paramsThe module settings
$appThe Joomla application
$inputThe request data

Common mistake

The database query is written right in the tmpl/default.php layout. It works, but the layout stops being plain markup: a site owner who overrides it in the template gets a copy of the query and breaks the module at the first update. The helper prepares data, the layout only prints it.

Thanks for reading!

Donate to the site — we work hard for you.