Prestashop allows you to customize the category view in your template folder but you can't show different categories in different ways. For example we wanted to show 2 items per row in some categories and 3 items per row in others.

We will create a front controller override that will search for our customized category templates structure.

1Desired template structure

Our template structure had some requirements:

  • Our tpl files should be separated of the template tpl standard files.
  • Each entity should have its own folder. For now we are going to deal with categories but probably we will need to add the same behaviour for products. So we would create categories, products, etc.
  • Each category will have his own folder. This way we will avoid conflicts with file includes.
  • We will use the category friendly url as folder name. This way the user will easily identify what is modifying. That's why we used this instead of category id. The only problem with this approach is that multilanguage sites have different friendly urls for the same category. To avoid this issue we will use the default language friendly url.
  • The main category tpl will be called category.tpl to allow users to copy&paste the default category template and then edit it.
  • Categories should use their hierarchy for templates. If one specific category hasn't a custom template but his parent has it the child category should use the parent's template.

Our final template structure will be something like:

layouts -> categories -> specific-category -> category.tpl

Graphically our theme folder will look like:

Desired template structure

For multishops you can add and extra top level/folder if you need to use different layouts for each shop. For example:

shop -> layouts -> categories -> specific-category -> category.tpl

In our case we needed to share layouts between shops so we will not use that extra-level.

2Controller Override

We will use the cool Prestashop feature that allows us to easily override and customize core controllers. In our case we need to customize the file:

override/controllers/front/CategoryController.php

The file is empty by default (just the class definition). We only need to override the initContent method that will load our template file.

We will also create a custom method to determine which tpl should be loaded.

File content:

class CategoryController extends CategoryControllerCore
{
	public function initContent()
	{
		parent::initContent();
		$this->setTemplate($this->getTpl());
	}
	protected function getTpl()
	{
		$layout = _PS_THEME_DIR_ . 'category.tpl';
		if ($parents = $this->category->getParentsCategories(Configuration::get('PS_LANG_DEFAULT')))
		{
			foreach ($parents as $parent)
			{
				$parent = (object) $parent;
				if (isset($parent->link_rewrite))
				{
					$categoryLayoutOverride = _PS_THEME_DIR_ . 'layouts/categories/' . $parent->link_rewrite . '/category.tpl';
					if (file_exists($categoryLayoutOverride))
					{
						$layout = $categoryLayoutOverride;
						break;
					}
				}
			}
		}
		return $layout;
	}
}

3Creating a custom template

The first step is to fix some wrongly called include files inside our category.tpl global file. All the include files should be relative to the theme folder. For example:

{include file="./product-sort.tpl"}

Should be:

{include file="$tpl_dir . /product-sort.tpl"}

Note that we added $tpl_dir. This makes the template always look for files into the default theme folder and allow us to only copy to our category folder the files that we really need to customize.

The full block that we have to fix is:

{if $products}
{include file="$tpl_dir./pagination.tpl"}
{include file="./product-sort.tpl"} {include file="./product-compare.tpl"} {include file="./nbr-product-page.tpl"}
{include file="./product-list.tpl" products=$products}
{include file="./product-sort.tpl"} {include file="./product-compare.tpl"} {include file="./nbr-product-page.tpl"}
{include file="./pagination.tpl"}
{/if}

We will replace it with:

{if $products}
{include file="$tpl_dir . /pagination.tpl"}
{include file="$tpl_dir . /product-sort.tpl"} {include file="$tpl_dir . /product-compare.tpl"} {include file="$tpl_dir . /nbr-product-page.tpl"}
{include file="$tpl_dir . /product-list.tpl" products=$products}
{include file="$tpl_dir . /product-sort.tpl"} {include file="$tpl_dir . /product-compare.tpl"} {include file="$tpl_dir . /nbr-product-page.tpl"}
{include file="$tpl_dir . /pagination.tpl"}
{/if}

That will be our default theme category.tpl

Now we are going to create a specific template for a category whose friendly url in our default language is "family-cars". We will create the folder:

themes/OUR_THEME/layouts/categories/family-cars

And inside we will copy the default category.tpl and the product-list.tpl files that we will use to customize the category and the product listing. In our new category.tpl file we will replace the line:

{include file="$tpl_dir . /product-list.tpl" products=$products}

with:

{include file="./product-list.tpl" products=$products}

with that change we are telling the tpl that we want to load the same product-list.tpl inside our category folder instead of the main theme product-list.tpl used for the non-customized categories.

4Using or skipping category hierarchy

Going further in our example we will now create a subcategory of "family-cars" with the friendly url "cross-wagon". We now have two options:

  1. If we do not create a custom folder for this category it will use parent's template
  2. We can also create a custom folder called "cross-wagon" and create its own customized template.

If you prefer no to use category hierarchy you only need to adjust the getTpl function:

	protected function getTpl()
	{
		$layout = _PS_THEME_DIR_ . 'category.tpl';
		$parent = $this->category;
		if (isset($parent->link_rewrite))
		{
			$categoryLayoutOverride = _PS_THEME_DIR_ . 'layouts/categories/' . $parent->link_rewrite . '/category.tpl';
			if (file_exists($categoryLayoutOverride))
			{
				$layout = $categoryLayoutOverride;
				break;
			}
		}
		return $layout;
	}

That's it! We now have our advanced layout system.

Did you use it? As we are planning to get this into the next Prestashop version we will love to know your thoughts or ideas.