Displaying different Joomla templates without using menu items

In the last post where we discussed Search Filtering in Joomla!, I briefly mentioned Joomla’s ability to assign different templates to each menu item, so your website can have one template for the main site and another for the blog, for example. It’s an impressive functionality, but there are still occasions where it falls short. In today’s article, we’ll look at an alternative method for applying different templates across your site using some custom PHP code. Without further ado, let’s get started!

When is Joomla’s core template functionality not enough?

For many users (perhaps even most), the core Joomla template functionality is flexible enough; since different templates can be assigned to menu items it’s relatively easy to segment off parts of your site and apply different templates accordingly. However, depending on the scope of your site there may be times when even this is not enough.

Let’s examine how the template system works. When you click on a menu item and load a specific page on your site, Joomla will check to see if a special template has been assigned specifically to that menu item. It is finds one, then this is applied. If there isn’t a specific template assigned, then the default template is used instead.

So what’s the default template? The one assigned to the frontpage? Actually, what is considered the default template is decided via the site hierarchy since menu inheritance rules apply in this case. An article that doesn’t have its own menu item will instead be assigned the same menu item (and thus the same template) as the category that it’s in. In extreme cases, if the category doesn’t have an assigned menu item then it’s going to rely on the main site for its details.

With these points in mind, we can see an issue with the solution Joomla employs to decide which template is applied:

  1. It’s not possible to automatically set a template to an individual article unless the template you want to use is already assigned to the category the article belongs to. In other words, posts will always have the same template as their parent category.
  2. To get around this, if we want an individual article to have a different template to its category then we can simply add the article as a menu item and assign a new template that way. However, this still doesn’t automatically assign the template; you’ll have to manually create a new menu item and assign the template each time an article is created. Plus, of course, if there’s a lot of items you want to apply an individual template to you’ll quickly end up with an impossibly-large menu! So for large or regularly-updated sites, this solution is a no-no.

Solving the Joomla template assignment issue with custom code

Fortunately, Joomla is a flexible framework, and it’s possible to get around this limitation with a bit of clever coding. To do this, we’ll need to create a plugin that will do a specific action when the onAfterRoute event occurs:

public function onAfterRoute() {
    $app = JFactory::getApplication();

    // ...
}

This event marks an important moment; when it occurs the process of rendering pages hasn’t yet started, but we’re able to find out what component and view will be called by Joomla. Now, we have to remember to limit the action of our plugin to the frontend only:

public function onAfterRoute() {
    $app = JFactory::getApplication();

    if ($app instanceof JApplicationSite) {
        // ...
    }
}

Then we can grab the information about the components and view that will be used on the specified subpage:

public function onAfterRoute() {
    $app = JFactory::getApplication();

    if ($app instanceof JApplicationSite) {
        $jinput = $app->input;
        $option = $jinput->getCmd('option', '');
        $view = $jinput->getCmd('view', '');

    // ...
    }
}

Next comes the important bit; by calling the setTemplate method, we can change the currently-assigned template to another:

public function onAfterRoute() {
    $app = JFactory::getApplication();

    if ($app instanceof JApplicationSite) {
        $jinput = $app->input;
        $option = $jinput->getCmd('option', '');
        $view = $jinput->getCmd('view', '');

        // ...

    if($option === 'com_content' && $view === 'article') {
            $app->setTemplate('protostar', $params);
        }
    }
}

This code isn’t perfect though; though the correct template is now in place, it loads the default template settings, which may not be what we want. Should we need to modify these default settings, then remember that the second argument of the setTemplate method includes its own template configuration, which we may create by using the jRegistry class:

public function onAfterRoute() {
    $app = JFactory::getApplication();

    if ($app instanceof JApplicationSite) {
        $jinput = $app->input;
        $option = $jinput->getCmd('option', '');
        $view = $jinput->getCmd('view', '');
        $params = new JRegistry();
        $params->def('templateColor', '#f00');
        $params->def('templateBackgroundColor', '#000');

        if($option === 'com_content' && $view === 'article') {
            $app->setTemplate('protostar', $params);
        }
    }
}

Using this method we may also create, for example, pre-configured sets of template settings and load them depending on the type of visitor that accesses the website to better suit their needs.

Summary

Though the core Joomla functionality allows for multiple templates to be assigned via menu items, you may find that there are situations where this is not the optimum method. With the features discussed above, we can avoid inefficient, inelegant menu configurations when managing templates on subpages of our website.

Share
This article was first published October 9th, 2015