Hook the Prestashop Layered Navigation Block to the Center Column

Being one of the most frequently asked questions on the official board, in this quick tip we will see how to hook the layered navigation module to the center column, above the product list/grid in Prestashop.

Step 1: overriding the Layered Navigation Module (Optional – 1.6.0.11 and newer only)

If you are not using the latest Prestashop version, you can jump to step 2 as module overrides were not available before that, and it’s necessary to amend the module directly. If you are, reach the override/modules/ folder and create a new one inside it called blocklayered. Inside that, add a file named blocklayered.php and paste the following inside php tags:

 
if (!defined('_CAN_LOAD_FILES_'))
    exit;
 
class BlockLayeredOverride extends BlockLayered
{
 
 
}

We have just setup the base file for the override. Go ahead and erase the class_index.php located in the cache/ folder, so that the new file is loaded and we can start extending the module.

Step 2 – Adding code for a new hook

It’s given that no hook sits on top of the product listing, if you are using, like me, the default template. If you are not, you might want to check out the category.tpl file for any usable spot, to avoid adding another one.

We need to add a few lines of code to register a new hook, and allow the Layered Navigation block to stick there as well. First off, if you are using the override method, simply add the following to our new file:

 
	public function install()
	{
		if(parent::install() && $this->registerHook('categoryTop'))
			return true;
		else return false;
	}

Else, if you are not using the override method, simply amend the original install() of the blocklayered.php file, by adding the new hook registration as follows (see the fourth line “&& $this->registerHook(‘categoryTop’)”)

	public function install()
	{
		if (parent::install() && $this->registerHook('header')
		&& $this->registerHook('categoryTop')
		&& $this->registerHook('categoryAddition') && $this->registerHook('categoryUpdate') && $this->registerHook('attributeGroupForm')
		&& $this->registerHook('afterSaveAttributeGroup') && $this->registerHook('afterDeleteAttributeGroup') && $this->registerHook('featureForm')
		&& $this->registerHook('afterDeleteFeature') && $this->registerHook('afterSaveFeature') && $this->registerHook('categoryDeletion')
		&& $this->registerHook('afterSaveProduct') && $this->registerHook('productListAssign') && $this->registerHook('postProcessAttributeGroup')
		&& $this->registerHook('postProcessFeature') && $this->registerHook('featureValueForm') && $this->registerHook('postProcessFeatureValue')
		&& $this->registerHook('afterDeleteFeatureValue') && $this->registerHook('afterSaveFeatureValue') && $this->registerHook('attributeForm')
		&& $this->registerHook('postProcessAttribute') && $this->registerHook('afterDeleteAttribute') && $this->registerHook('afterSaveAttribute'))
		{
			if (version_compare(_PS_VERSION_, '1.6.0', '>=') === true)
			{
				// Hook the module either on the left or right column
				$theme = new Theme(Context::getContext()->shop->id_theme);
				if ((!$theme->default_left_column || !$this->registerHook('leftColumn'))
					&& (!$theme->default_right_column || !$this->registerHook('rightColumn')))
				{
					// If there are no colums implemented by the template, throw an error and uninstall the module
					$this->_errors[] = $this->l('This module need to be hooked in a column and your theme does not implement one');
					parent::uninstall();
					return false;
				}
			}
			else
				$this->registerHook('leftColumn');

			Configuration::updateValue('PS_LAYERED_HIDE_0_VALUES', 1);
			Configuration::updateValue('PS_LAYERED_SHOW_QTIES', 1);
			Configuration::updateValue('PS_LAYERED_FULL_TREE', 1);
			Configuration::updateValue('PS_LAYERED_FILTER_PRICE_USETAX', 1);
			Configuration::updateValue('PS_LAYERED_FILTER_CATEGORY_DEPTH', 1);
			Configuration::updateValue('PS_LAYERED_FILTER_INDEX_QTY', 0);
			Configuration::updateValue('PS_LAYERED_FILTER_INDEX_CDT', 0);
			Configuration::updateValue('PS_LAYERED_FILTER_INDEX_MNF', 0);
			Configuration::updateValue('PS_LAYERED_FILTER_INDEX_CAT', 0);
			Configuration::updateValue('PS_ATTRIBUTE_ANCHOR_SEPARATOR', '-');

			$this->rebuildLayeredStructure();
			$this->buildLayeredCategories();

			$products_count = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'product`');

			if ($products_count < 20000) // Lock template filter creation if too many products
				$this->rebuildLayeredCache();

			self::installPriceIndexTable();
			$this->installFriendlyUrlTable();
			$this->installIndexableAttributeTable();
			$this->installProductAttributeTable();

			if ($products_count < 5000) // Lock indexation if too many products
			{
				self::fullPricesIndexProcess();
				$this->indexUrl();
				$this->indexAttribute();
			}

			return true;
		}
		else
		{
			// Installation failed (or hook registration) => uninstall the module
			$this->uninstall();
			return false;
		}
	}

Then, simply add the following new hooking method to your blocklayered file (whichever you are modifying)

	public function hookCategoryTop($params)
	{
		return $this->hookLeftColumn($params);
	}

Before proceeding further, make sure you actually reset the Layered Navigation module from the modules section of the back office, so it register the new hook (or uninstall, then install again if that doesn’t work).

Adding the new hook to the category.tpl template file

We will be using the new method to add hooks in Prestashop, introduced since version 1.5. Open up the category.tpl file of your template, locate a suitable spot and paste the following in:

{hook h="categoryTop"}

Tip: I suggest you do it right after the {if $products} statement, before the product list. Here is where I did it, on a default-bootstrap template on 1.6.0.11:

...

{if $products}
            {hook h="categoryTop"}
			<div class="content_sortPagiBar clearfix">
            	<div class="sortPagiBar clearfix">
            		{include file="./product-sort.tpl"}

...

Save and test, the module should be popping out in the middle column:

Hook the Prestashop Layered Navigation Block to the Center Column - hooked

What to do if it doesn’t? First, make sure that your template has been recompiled: reach Advanced Parameters > Performance in the back office, and set Template Compilation to Recompile templates if the files have been updated at least, or even Force Compile. Refresh the Front office afterwards.

If you still don’t see anything, there might be a typo in the hook you register. Check all names, then try killing the script on the hooking method as follows:

	public function hookCategoryTop($params)
	{
		die('I am here!');
		return $this->hookLeftColumn($params);
	}

If you see the page rendering interrupted by the “I am here” text, the hook should work, check that blocklayered is properly configured. If not, check, once more, for typos in function names, registrations and calls. If you are using the override and it still won’t work after clearing cache, switch to core modifications.

Step 3 – Making it work

If you try out the module now, having it hooked to both either of the side columns and to the center one, you’ll be disappointed to notice it won’t work. Why? A javascript error will be triggered upon click.

To fix it, simply unhook the Layered Navigation from the side columns, leaving only one instance of it running in the center one. Reach Modules > positions and look the the module’s instances in displayLeftColumn and displayRightColumn. Unhook both, just in case.

Beauty Pass

There is no need to say a huge list of features/attributes/whatever shown at the very top of the product list will force people to scroll down to see products. It’s therefore better to give the new block some better styling. Open up themes\default-bootstrap\css\modules\blocklayered\blocklayered.css (or the one of your template, or create it if it’s not there).

At the cery end, add:

#center_column .layered_filter{
  float:left;
  width: 50%;
}
#center_column .layered_filter:nth-child(2n) {
  clear:left;
}

It’s just some basic styling to shorten the height, but it will give you the right pointer to customize it further.

We’re done!

You like the tuts and want to say "thank you"? Well, you can always feel free to donate:

  • Oswaldo Franco

    Greetings friends, I want to know if it is possible to show the contents of the blocklayered in a fancybox to show it on mobile.

    regards

  • NemoPS

    You might need to check if it has a disabling if statement inside displayHeader, in case the module is not hooked to any column

    • Alex

      Hi,

      you need to comment line 681,682 and 683 from blocklayered.php

      regards,

  • vertigo

    Hi, i did this by your tutorial, but when i wrote code

    public function install()
    {
    if(parent::install() && $this->registerHook(‘categoryTop’))
    return true;
    else return false;
    }

    My site immediately make error: 500 ..

    What should i do?
    Ty,
    podpora@northstyle.cz

  • Manu Torres

    hi, i have this problem: i follow your steps. if i have enabled left column, module works fine, but if i remove left column, the module dont work… module is not hooked to the leftcolumn… also i dont see any javascript error… it looks like that is mandatory to enable left column, but that dont make sense :S what will be the problem???

    • NemoPS

      You might have to check the original code for the left column hook, it might be set to return false if the left column is not enabled

      • F.V

        Hello Nemo,

        Do you have any more clue ? Couldn’t solve this yet, it is on classic 1.6.1.6

    • F.V

      Hello Manu, did you found the answer of this ? I got same problem but i couldnt fix it for now

  • Davide

    Hello, I have the latest version of prestashop 1.6.14, after editing I do not see the new hook in modules positions, I noticed that the new layered block code is different. Some advice?

  • stefano

    This works, but I have great problem; to have hook modified I need to uninstall and reinstall module; when I reinstall my server start a lot of processes and has a very high load cpu !! Seems to do too many queries on sql , do you know why is this ?

  • sattar

    Thank you! this is great.
    the only problem is it doesn’t display price filter. any clue?

  • presta

    Didnt work for me (both ways), css and js from the plugin is not loading. Any ideas?

  • Jimy

    Hi.
    First thank you for tutorials.
    Unfortunately this not work for me. I did step by step (PS 1.6.0.11),and module showing up but filtering doesn’t work. Tried without any other position, just center,but nothing. As a matter of fact, when left column and header position are enabled, then at least spinning gif is there! :)
    However, I think that is some problem with jQuery. Somewhere I found that Layered Navigation Block MUST be in left column?!

    • NemoPS

      Of course not, as it can be in the right as well. if it doesn’t work by default either, chances are the template or module overrides (tpls, js) are broken. Look for js error on the page anyway :)

      • Jimy

        Thank you for your tip!
        I tried without override method and now, it seems, work fine. :)

You like the tuts and want to say "thank you"? Well, you can always feel free to donate: