How Joomla Handles Module Display

If you have ever set up a Joomla website you will be familiar with the Joomla module manager. This allows you to create, publish and assign modules to a module position and to Joomla menu items. The purpose of this article is to look a little bit 'under the hood' and explain how module management actually works. That is, how does Joomla know which modules to display on which pages, and where to put them?

We also look at the question of whether it is possible to extend the logic of Joomla module display, to include complex conditional logic, for example if you only want to display a module to particular user groups, or only want to display a module on the checkout page of your shopping cart extension, or only want to display a module to a user if it is their birthday.

When you save a new module in the Joomla module manager, the information controlling its display, including the module paramters, is saved in the xxxx_modules database table. The information on the module menu assignment is saved in the xxxx_modules_menu table. If you look at this table in your database admin you will see that it contains two fields: moduleid and menuid. The first id corresponds to the entry in the modules table, the second field corresponds to the id field in the xxx_menu table. This number corresponds to the ItemId parameter that is passed in a native Joomla (non-SEF) URL, and can also be found by finding the item in the Joomla menu manager, and then checking the id number in the right hand column.

If a module is assigned to all pages the menuid field value in the modules_menu table will be zero; if a module is assigned to selected Joomla pages there will be an entry for each menu item in the modules_menu table.

This has some important consequences for the handling of Joomla modules. Firstly, it is only possible to assign a module to pages that correspond to a Joomla menu item. This can make life difficult if you are using an extension such as Virtuemart, where the pages displayed (for example individual product pages, or the checkout pages) do not necessarily correspond to a Joomla menu item.

Secondly, a module is either assigned to a page or it is not, there is no opportunity for conditional logic, for example if you only want to display a module to particular user groups. Joomla offers some built in conditional logic, for example the 'Access' parameter controls, but it is very limited in its scope. Moreover, because of the way that module assignment is hard-wired into the Joomla core, it is very difficult to override this behaviour. In my view this is one of the biggest limitations of Joomla. It is a system which has persisted virtually unchanged since Joomla 1.0, and could do with an overhaul.

Currently the only way to override this behaviour is to use conditional logic that suppresses module output when it is not required. This is the approach used by our VM Modcontroller module, which can be used to control module display on Virtuemart pages. Essentially the way the the VM Modcontroller module works is to check a variety of conditions such as the product category, the Virtuemart page name, the manufacture, shopper group etc (the conditions are chosen as options in the module parameters). Depending on whether the conditions are satisfied, the controller module either loads the desired module content and renders it, or renders nothing. Note that, for the reasons explained above, the controlled module cannot be unpublished or unassigned to a position, because that information is controlled directly by the values stored in the modules database table. This can be problematic, depending on how the site template handles empty modules, and result in undesired extra output from the module chrome.

Module Positions and Module Chrome

One of the most important things to understand about modules is that the actual display, including the module position, is entirely handled by the template, not by Joomla itself. The content of a module is rendered using module 'chrome' which controls the layout surrounding the module. You can find the Joomla default module chrome in the file templates/system/html/modules.php. Any template can also define its own chrome, simply by including its own modules.php file. Module chrome can be used for example if you want each module to be surrounded by a div tag, with special styling attached to it. In that case you would use code something like the following:-

function modChrome_example($module, &$params, &$attribs)
{
if (!empty ($module->content)) : ?>
<div class="moduletable<?php echo htmlspecialchars($params->get('moduleclass_sfx')); ?>"
style="padding:6px;border:1px solid;margin:4px">
<?php if ((bool) $module->showtitle) : ?>
<h3><?php echo $module->title; ?></h3>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
<?php endif;
}

This would result in a module enclosed in a div element with a border of 1pixel, a margin of 4pixels and padding of 10pixels. In practice it would give you greater flexibility to simply assign an additional class to the module and define the styling in the template stylesheet, but I include this example to illustrate the principle.

Notice that this example to test if there actually is any module->content (using if (!empty ($module->content)) before outputting anything. Unfortunately not all species of Joomla and template chrome include this test, which leads to problems with overriding module display by suppressing the output. The result of not including this test is that you may see empty modules where the module output should be suppressed, instead you may see a module title and possibly an outline as well.

Module positioning is entirely under the control of the template. There is no requirement for a template to include any particular position at all. Module positions are normally implemented in the template index.php file, using code such as this:-

	<jdoc:include type="modules" name="position-8" style="example" />

The name parameter is simply the position name. The style parameter corresponds to the module chrome, in this case the chrome used would be our modChrome_example defined above.

Sometimes the template will include a test to see if there are any modules assigned to a position before rending the position, using the countModules() method:-

	<?php if ($this->countModules('position-7')) : ?>
<div id="rightside" class="rightsidebar">
<!-- Begin Right Sidebar -->
<jdoc:include type="modules" name="position-7" style="xhtml" />
<!-- End Right Sidebar -->
</div>
<?php endif; ?>

It is important to understand what the countModules method does, it simply checks the database modules table for the number of published modules assigned to a particular position. If you are trying to control module display by suppressing the output then this will give a misleading answer, because a module will still be assigned to the position whether or not it has any output. This can lead to the module position still being rendered, usually as an empty space, when there is no module output to place there. The only way to do with this problem is edit the template to include additional programming logic to check whether the module contents are empty. For example the php code below would check whether the main bottom template position should be rendered:-

//check bottom module position
$showMainBottom = false;
$bottomModules = JModuleHelper::getModules( 'mainbottom' );
if(count($bottomModules)>0)
{
foreach($bottomModules as $bottomMod)
{
if(JModuleHelper::renderModule($bottomMod) != "")
{
$showMainBottom = true;
}
}
}

then to render the module position you would use:-

	<?php if ($showMainBottom) : ?>
<div id="mainbottom">
<jdoc:include type="modules" name="mainbottom" style="xhtml" />
</div>
<!-- mainbottom end -->
<?php endif; ?>

 

Controlling Module Display

So what is the best way to include conditional logic to control module display? We have already outlined the procedure used by our VM Modcontroller module, and described the difficulties with this approach. However if you just want to do something simple like only display a module to a user on their birthday there is a slightly simpler alternative, which is to do this through the module chrome:-

function modChrome_birthday($module, &$params, &$attribs)
{ $user = JFactory::getUser(); /* now include code to check whether it is user's birthday, eg check user profile */
if (!empty ($module->content)&& $isBirthday) : ?>
<div class="moduletable<?php
echo htmlspecialchars($params->get('moduleclass_sfx')); ?>">
<?php if ((bool) $module->showtitle) : ?>
<h3><?php echo $module->title; ?></h3>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
<?php endif;
}

then to include it in the template you would just need to include this code:-

<jdoc:include type="modules" name="birthday" style="birthday" />

You would also need to assign the module to the position 'birthday' in the Joomla module manager.

So How Could Joomla's Module Handling Be Improved?

The problem is that the fundamentals of Joomla's module handling are hardwired into the Joomla core. These are handled by the JModuleHelper class, through the getModule and getModules methods. My idea is that much greater flexibility could be introduced into the system if JModuleHelper were to support its own plugin system. Whenever a module is loaded the plugin onModuleLoaded event could be fired, passing the module as a parameter. This would then allow any relevant plugins to modify key module properties, such as whether or not it is published, the title, content and positioning. This would allow any required conditional logic to be introduced to control module display, rather than having to rely on values derived from the database, and then fudging the results. It would allow the countModules method to function correctly, thus avoiding any template problems.

Alternatively perhaps some system of template overriding could be devised. Some templates, eg the Rockettheme gantry framework, or the Yootheme warp framework already contain a lot of code to control module display. A more standardized system might make a lot of sense.

There are signs that future releases of Joomla (beyond the 3x series) may address these problems, because I note that the JModuleHelper class has now been moved to the legacy library Joomla, implying that it will eventually be replaced.

Author Profile