A deeper look at Prestashop Hooks

Today, we are going to cover one of the most overlooked feature of Prestashop: Hooks. I’ll be teaching you what these mysterious entities really are, and how to bend them to your will, and bring your site to the next level of customization.

Download Project Files

What are hooks?

If you have been using Prestashop for quite some time, I bet you found yourself saying “Why in the world can’t I place something there? I really want to do it!” in more than one occasion. Yes, it can be frustrating, because Prestashop only allows you to execute your modules in specific spots, defined by the software itself. These places are commonly known as hooks. And this is actually all what hooks are, as the name suggests: they represent definite points of the code which you can use to run your own module’s functions.

If this may be considered as a limitation, since it forces the developer to only use those specific points to run a module’s code without touching the core files, it’s also a powerful and easy solution to greatly improve Prestashop’s basics functionalities. Actually, hooks make your life A LOT easier when extending the package. At least, you don’t have to mess for ages with XML and Zend Framework ugly PHP (have I heard someone screaming Magento?).

Anyway, if you are a developer, and know how to code a prestashop module, you’ll be quite used to the following structure:

public function hookLeftColumn($params)
{
    /* Code to be executed */
}

This function allows the module to be hooked to the left column, and running proper code from there, be it something to display to the user, or stas gathering stuff. In any case, you will always need to run a hookSomewhere function to run the module’s code in a specific place.

 

Visual Hooks VS Action Hooks

Hooks can be basically grouped into 2 main groups: Visual Hooks, and Action Hooks.

The first ones are generally used to display content to your website, and provide a visual feedback to the customer. While there are in fact back Office visual hooks, like the one used to display new tabs on the Stats page, most of them are defined by controllers in front office, and assigned to variables to be executed within the template. An example of this is the “Left Column” hook we saw previously, used to show modules on the left column of the base template

 

Action hooks are, on the other side, deputed to only run code, without actually display content. They are placed both in class and controller files, and may come in handy when we need to gather data thrown by a class, manipulate it, or use it for  purposes other than Prestashop’s default one. As the name suggests, they occur when a spacific action takes place. An example of action hook is the “cart” hook, executed in the Cart.php Class when a cart is created or updated.

To exemplify, let’s say we have a “best sales” module, and it uses database caching to optimize performance. It retrieves best sellers from a cached version of the product list created once in a while. Well, this once in a while can be set in two ways: the traditional way is to set up a cron job, and refresh the list once every hour, or day, or so; the other way would be using hooks. We could hook the module to “newOrder”, which is a hook that executes when a new order is placed, and code a function that refreshes data in that particular moment. This way, there would be now need to fetch all product data every time the page reloads, thus increasing our site’s speed. Of course, this is just an example (taken from one of my modules, Best sales of the day/week/month/period, which you can find here), and there are other many things you can do with action hooks.

Whichever purpose hooks have, they all share the same basic structure:

  • A database entry in the ps_hook table 

Prestashop Hooks table

This is the core part of the hooks, since it’s what makes Prestashop know whether the specific hook we are currently calling exists or not.

 

  •  The hookExec() function which executes it

It’s the function that runs the hooks execution, and therefore all hookNameOfTheHook() function associated to it(see next). The function is defined in the Module Class, and can be passed a number of parameters to be stored in the $params variable of the executing function.

Module::hookExec('nameofthehook')
Module::hookExec('nameofthehook', $params_array)

When creating a front office visual hook, instead of directly executing the hooks attached modules, the action is assigned to a variable to be called by smarty within the template.

self::$smarty->assign('HOOK_NAMEOFTHEHOOK', Module::hookExec('nameofthehook'));

In this case, you would also need to add the following code to the template file where you wanted to display the hook’s content

{$HOOK_NAMEOFTHEHOOK}


  • A hookNameOfTheHook() function to be placed in modules in order to hook them

Without this, a module would not be hooked to anything and would never execute. This last function is the most important one, since it allows you to perform any action for the desired hook. We already saw the code for the HookLeftColumn() function.

public function hookLeftColumn($params)
{
    /* Code to be executed */
}

This function usually returns a template file in front office hooks

return $this->display(__FILE__, 'filename.tpl')

 

 

Let’s go into action: creating a new Hook in Prestashop

Now that we know enough about hooks, let’s create a new hook that will allow us to display modules content at the beginning of  each category page.

The first step will be to let Prestashop know the hook exists, so let’s add it to the database. We can go 2 ways: log in to phpmyadmin (or any sql manager) and add the column manually; or create a module which, when installed, will add the hook.

The database way:

Log in to your sql manager. In your prestashop database, look for the table ps_hook (remember, ps_ is just the default prefix, you can have anything instead of that! Take note of your prefix). If you’re using phpMyAdmin, click on the yourprefixHook table, then Insert, and add values for the name (which should be all underscore and without spaces), title and description then click add. Alternatively, you can use run this SQL query:

INSERT INTO `ps_hook` (`name`, `title`, `description`) 
VALUES ('category', 'Category', 'Hooks before the product list in a category');

 

The module way:

If the hook is only used by a module, we can also bind it to the module itself, and add it in the installation process. Let’s create a function that looks like this:

protected function addHook() {
    $check = Db::getInstance()->getRow('
			SELECT name
			FROM '._DB_PREFIX_.'hook
			WHERE name = "category"
			');

    if (!$check) {
	$query = "INSERT INTO "._DB_PREFIX_."hook (`name`, `title`, `description`) VALUES ('category', 'Category', 'Hooks before the product list in a category');";
	if(Db::getInstance()->Execute($query))
	    return true;
	else
	    return false;
    }
    else return true;
}

The $check part is useful to know if another hook with the same name exists, since creating douplicates will definitely cause problems!

 

Executing the hook

Now that prestashop has the hook data stored, it’s time to run it’s execution

self::$smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));

We can place this code in the FrontController.php file, or any other controller, since we are going to use the hook for display purposes. Using the FrontController saves us the time of thinking where exactly it should run, because assigning the variable in the DisplayHeader function will set it for every front page, before even one of the other hooks is assigned. So, to add the assignment to the Front Controller, let’s create a new FrontController.php file, place it into override/classes, and fill it with the following code.


<?php 

Class FrontController extends FrontControllerCore
{

	public function displayHeader()
	{
		if (!self::$initialized)
			 $this->init();

			self::$smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));

		parent::displayHeader();		
	}

}

 

Note the if (!self::$initialized)  $this->init(); snippet at the beginning of the function. This ensures the controller is properly initialized, and fixes problems in pages such as payment or order confirmation..

Even though using the front controller saves us the time of having to scrub through all other controllers to find the right position to execute it, be aware that it will be assigning the execution for every front page of the shop. So, for our purposes, it would have been better to add the assignment in the process() function of the CategoryController. In the end, of course, the choice is all up to you. For the sake of it, here is what adding the code to a categoryController override would have looked like

class CategoryController extends CategoryControllerCore
{

    public function process()
    {
        parent::process();
        if (!($id_category = (int)Tools::getValue('id_category')) OR !Validate::isUnsignedId($id_category))
            $this->errors[] = Tools::displayError('Missing category ID');
	else
		{
                     self::$smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));
          }
    }
}

 

Now, let’s add the hook to the template

Let’s open up the category.tpl file of our template.Just before this code

{if $products}

Which is line 90 of the prestashop_new template, add the following

{$HOOK_CATEGORY}

Most of the work it’s done, and we have just successfully added a new hook in Prestashop!

Creating a module to be hooked

…Yay, okay, but we need to test this new hook, or else we don’t know if it really works or not. I’ve prepared a testing module, which can be found as an attachment at the beginning of the post. Grab it, copy the “testing” folder inside the modules folder and open the testing.php file.

If you know something about modules, you’ll definitely know they have to be registered to a hook before they can be executed. If you don’t want to do it manually from the positions tab in back office, add the following code in the install() function:

public function install()
{
    if (!parent::install() OR
	!$this->registerHook('Category'))
        return false;
    return true;
}

Now, at the bottom of the file, create the hookCategory Function:

public function hookCategory($params)
{
    global $cookie, $smarty;
    return $this->display(__FILE__, 'testing.tpl');
}

 

And that’s all!

Let’s install the module, go to a category page of the shop and see if the template’s content appears where we placed the hook variable. It’s likely we won’t see anything at the moment, but don’t fear. Since Prestashop uses caching, we must first re-compile the cache to see changes. Let’s go to preferences, then performance in back office, and turn on the option “Force Compile”, then refresh the category page. At this point, we should see a piece of text saying “Howdy guys! testing new hooks” If you don’t, since the Force Compile feature is a bit buggy, go to the Tools/Smarty/Compile folder and delete everything except the index.php. This should fix it, and you should be able to see the text.

Conclusion

We’re done! Thanks for reading. If you still have questions about how to create new hooks, feel free to contact me and I’ll be glad to help you.

Additional Resources

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

  • http://www.lancastrian-it.co.uk/ shoulders

    there is also a new method of creating hooks i am messing with. here is the forum thread i am reading:

    {hook h=’displayMyNewHook’}

    http://www.prestashop.com/forums/topic/173027-solved-how-to-create-a-new-hook-in-15-am-i-doing-it-wrong/page__hl__load%20products__st__20

    thanks

  • Deepan

    When we upgrade prestashop, may it` will gone so again we have to add hook function in module class right.

    what`s solution for this

    • http://nemops.com Nemo

      HI,
      I don’t know if I got the meaning of your question. If you meant “do I have to add new hooks again after the upgrade”? That depends on where you added them. If you used overrides, no, you probably won’t have to do it. Otherwise, yes.

  • rrdavik

    First of all.

    Well done! nice article..

    I have some doubts about it.

    I was wondering how the controller extension class is package in the module…
    If I wanna make an independent module? Where I should place this controller?

    Inside the module foler? inside override?

    Also I don’t have clear where to override the tpl’s… I tried in the module directory, and in theme directory… and I couldnt make it work…

    Thanks in advance!

    • http://nemops.com Nemo

      Hi,
      Controller extensions were introduced in 1.5, and in any case it’s a whole different story from hooks. It’s hard to explain the entire concept in a post, maybe i’ll make a tut about it sometime soon.
      At any rate, the controller must be placed in the module’s folder, inside a “controller” folder and has tobe given a specific name (you can find info in the prestashop doc i believe).
      For the tpls, you have to go to the template folder, them modules, create a folder with the module name inside it and place the tpl. Of course, if the module uses different views it’s another whole story

Westhost Website Builder 20% off 300x250

Store Top Sales

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