Joomla Template Overrides Methods
Joomla template Overrides is difficult, even for joomla expert. As a joomla developer may be you already knew how to find the correct file to override the layout of Joomla components or modules. In this tutorial I will show you some methods to find the correct file to override the Joomla components or modules layout.
1. Start from the menu
To override the layout of Joomla components or modules first you have to find the menu item of that page. for example we will customize the layout of the home page then you should go to menu manager, select the Main Menu and click Home menu item.
In Edit Menu Item page you can see the Menu Item Type and Link of this menu item. To find the correct file to override you should extract some informations from the Link of this menu item. for example the link is index.php?option=com_content&view=featured, from this url we can see that the component name is com_content and the view name is featured. or maybe your link is index.php?option=com_content&view=category&layout=blog&id=2, from this url we can see that the component name is com_content, the view name is category and the layout is blog. If the link does not have a parameter called layout then it is using default.php as layout file.
2. Go to Extensions > Template Manager
In template manager page, from the left sidebar click Templates and on you current template for example protostar click Protostar Details and Files. In Customise Template page click Create Overrides tab
For example the view name on the Menu Item is featured , then you should click under Components, com_content > featured and Joomla will copy all layout files from components/com_content/views/featured/tmpl to templates/yourtemplatename/html/com_content/featured for you. Now you should be able to customize Joomla component or module layout under your custom template.
3. Updating joomla layout file
Now let’s find the correct file to update. From the step 1 we can see that the view name is featured and the layout is default. so we should edit templates/yourtemplatename/html/com_content/featured/default.php. Note: you should familiar with PHP to edit joomla templates. From this step you should be able to customize the HTML tags and some logic in the layout file. In a layout file sometime you will find Joomla loads another layout file using echo $this->loadTemplate(‘childlayout’) or using echo JLayoutHelper::render(‘layout.path’), the last method is only available on Joomla 3. For example you find this code echo $this->loadTemplate(‘links’); on a layout file, it means that Joomla will load a file called default_links.php in this featured folder. The file name of child layout file is parentlayout_childlayout.php.
Joomla 3 has new feature which allow us to share layout across views or extensions with JLayout. You can see the docs at http://docs.joomla.org/Sharing_layouts_across_views_or_extensions_with_JLayout. So basically Joomla 3 shares the common layout like item title of the blog or tag in a folder layouts/joomla under your Joomla site. For example on file templates/yourtemplatename/html/com_content/featured/default.php you can find this line of code:
<?php if ($params->get('show_tags', 1) && !empty($this->item->tags)) : ?> <?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?> <?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?> <?php endif; ?>
It means that Joomla will render a layout file layouts/joomla/content/tags.php but we should not modify that file directly because this layout folder will be overwritten if you upgrade your Joomla. We should override that layout by creating a folder templates/yourtemplatename/html/layouts/joomla/content and copy that layouts/joomla/content/tags.php to templates/yourtemplatename/html/layouts/joomla/content and now you can modify that tags.php file under your custom template.
4. How to quickly Find the Correct Layout file
Soon or later you will get tired from opening one by one layout file under the view folders to get correct layout file to edit. It’s because Joomla usually load another template or layout file in a layout file. So Is there any way to know the correct layout file quickly? There is, as far as I know Joomla uses two different methods to load a layout file, the first is using echo $this->loadTemplate(‘layout’); and the second is using echo JLayoutHelper::render(‘layout.path’);. so we should modify these functions to know the path of a layout file.
Lets start from the first method loadTemplate, this method is from JViewLegacy class and the file path is libraries/legacy/view/legacy.php. To know the path of a loaded layout file we can simply add some php code to loadTemplate function. Now edit your libraries/legacy/view/legacy.php and find loadTemplate function its on line 607 on Joomla 3.0.2 and just add this line of code before ob_start();
if(substr_count($_SERVER['REQUEST_URI'],"/administrator") < 1) echo '<!--path:'.$this->_template.'-->';
here is the modified loadTemplate function
/** * Load a template file -- first look in the templates folder for an override * * @param string $tpl The name of the template source file; automatically searches the template paths and compiles as needed. * * @return string The output of the the template script. * * @since 12.2 * @throws Exception */ public function loadTemplate($tpl = null) { // Clear prior output $this->_output = null; $template = JFactory::getApplication()->getTemplate(); $layout = $this->getLayout(); $layoutTemplate = $this->getLayoutTemplate(); // Create the template file name based on the layout $file = isset($tpl) ? $layout . '_' . $tpl : $layout; // Clean the file name $file = preg_replace('/[^A-Z0-9_\.-]/i', '', $file); $tpl = isset($tpl) ? preg_replace('/[^A-Z0-9_\.-]/i', '', $tpl) : $tpl; // Load the language file for the template $lang = JFactory::getLanguage(); $lang->load('tpl_' . $template, JPATH_BASE, null, false, true) || $lang->load('tpl_' . $template, JPATH_THEMES . "/$template", null, false, true); // Change the template folder if alternative layout is in different template if (isset($layoutTemplate) && $layoutTemplate != '_' && $layoutTemplate != $template) { $this->_path['template'] = str_replace($template, $layoutTemplate, $this->_path['template']); } // Load the template script jimport('joomla.filesystem.path'); $filetofind = $this->_createFileName('template', array('name' => $file)); $this->_template = JPath::find($this->_path['template'], $filetofind); // If alternate layout can't be found, fall back to default layout if ($this->_template == false) { $filetofind = $this->_createFileName('', array('name' => 'default' . (isset($tpl) ? '_' . $tpl : $tpl))); $this->_template = JPath::find($this->_path['template'], $filetofind); } if ($this->_template != false) { // Unset so as not to introduce into template scope unset($tpl); unset($file); // Never allow a 'this' property if (isset($this->this)) { unset($this->this); } // Start capturing output into a buffer if(substr_count($_SERVER['REQUEST_URI'],"/administrator") < 1) echo '<!--path:'.$this->_template.'-->'; ob_start(); // Include the requested template filename in the local scope // (this will execute the view logic). include $this->_template; // Done with the requested template; get the buffer and // clear it. $this->_output = ob_get_contents(); ob_end_clean(); return $this->_output; } else { throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_LAYOUTFILE_NOT_FOUND', $file), 500); } }
if(substr_count($_SERVER['REQUEST_URI'],"/administrator") < 1) echo '<!--path:'.$path.'-->';
and here is the modified render function:
/** * Method to render the layout. * * @param object $displayData Object which properties are used inside the layout file to build displayed output * * @return string The necessary HTML to display the layout * * @since 3.0 */ public function render($displayData) { $layoutOutput = ''; // Check possible overrides, and build the full path to layout file $path = $this->getPath(); if ($this->options->get('debug', false)) { echo "<pre>" . $this->renderDebugMessages() . "</pre>"; } // If there exists such a layout file, include it and collect its output if (!empty($path)) { //dont show on backend if(substr_count($_SERVER['REQUEST_URI'],"/administrator") < 1) echo '<!--path:'.$path.'-->'; ob_start(); include $path; $layoutOutput = ob_get_contents(); ob_end_clean(); } return $layoutOutput; }
Note that these changes will be lost if you upgrade your Joomla site. Now you can using firebug or chrome developer tools to see the layout file path on a page.