Adding Previous and Next navigation buttons to the Prestashop product page

To allow an easier navigation through categories, let’s add Previous and Next product navigation buttons to each product page in Prestashop

  • Prestashop version: 1.5, 1.6
Download Project Files

Please notice project files are from 1.6.0.9

Introduction

Although I only tested this code on Prestashop 1.6, it should equally work on 1.5 as the database structure didn’t change. That said, we need to edit/extend the following files:

  • classes/Product.php (to grab previous and next products)
  • controllers/front/ProductController.php (to assign links to the template)
  • themes/default-bootstrap/product.tpl (to add the buttons)

As always, I recommend overriding whenever possible; therefore, we will extend the first 2 files and directly modify the template one.

Additionally, given that a product can belong to different categories, we will only navigate through the default one, to make things easier.

Step 1 – Retrieving the previous and next product

First off, we need some data to work with. Neither previous nor next product are assigned to the product page, so we need to get them first. As mentioned above, to simplify we will only retrieve the ones that come before and after in the default product category. It is indeed possible to use the previously visited category, but things can get quite complicated and overly troublesome (it might be a good subject for another tutorial though!).

Create a new file inside override/classes and call it Product.php, and paste the following inside php tags:

class Product extends ProductCore
{
}

Then, let’s create the method we need, and start by grabbing the current product’s position in its default category:


	public function getAdjacentProducts()
	{

		$position  = Db::getInstance()->getValue('SELECT position FROM '._DB_PREFIX_.'category_product WHERE id_product = ' . (int)$this->id . ' AND id_category = ' . (int)$this->id_category_default);
	}

Once we get that, we can retrieve previous and next products:


	public function getAdjacentProducts()
	{


		$position  = Db::getInstance()->getValue('SELECT position FROM '._DB_PREFIX_.'category_product WHERE id_product = ' . (int)$this->id . ' AND id_category = ' . (int)$this->id_category_default);

		// get products that are before and after
		
		$previous = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
			SELECT cp.id_product, pl.link_rewrite, cp.position, pl.name
			FROM '._DB_PREFIX_.'category_product cp
			LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (cp.id_product = pl.id_product)
			LEFT JOIN '._DB_PREFIX_.'product p ON (cp.id_product = p.id_product)
			WHERE p.id_category_default = '.(int)$this->id_category_default.' AND (cp.position < '. (int)($position ) .' ) AND cp.id_category = ' . (int)$this->id_category_default .' AND pl.id_lang = '.(Context::getContext()->language->id).'
			ORDER BY cp.position DESC');

		$next = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
			SELECT cp.id_product, pl.link_rewrite, cp.position, pl.name
			FROM '._DB_PREFIX_.'category_product cp
			LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (cp.id_product = pl.id_product)
			LEFT JOIN '._DB_PREFIX_.'product p ON (cp.id_product = p.id_product)
			WHERE p.id_category_default = '.(int)$this->id_category_default.' AND (cp.position > '. (int)($position ) .' ) AND cp.id_category = ' . (int)$this->id_category_default .' AND pl.id_lang = '.(Context::getContext()->language->id).'
			ORDER BY cp.position ASC');


		return array('previous' => $previous, 'next' => $next);
	}


Explanation: We are using basically the same qurery for both the previous and next product. For the previous, we get the very first product that has a lower position, given the conditions. For the next, the one that has the immediately higher one. Notice we only grab products from the same default category, and that is why we can’t simply use position + 1 and position – 1 in a single query (we would have gaps)

Step 2 – Assigning products to the Product page

It’s time to assign the variables we got to the product page. Create a new override, this time inside override/controllers/front and call it ProductController.php. Then, as always, initialize the class override:



Class ProductController extends ProductControllerCore
{

	public function initContent()
	{
	
		parent::initContent();
	}	
}

We are going to extend the initContent() method, as you can see. Therefore, inside it, and before calling the parent’s initContent(), paste the following:



		$adjacent_products = $this->product->getAdjacentProducts();

		$this->context->smarty->assign(array(
			'prev_product'=> $adjacent_products['previous'],
			'next_product'=> $adjacent_products['next']
		));


Explanation: Nothing special here, we simply use the previously created method, and then assign previous and next products

Our final override should look like this:

Class ProductController extends ProductControllerCore
{

	public function initContent()
	{


		$adjacent_products = $this->product->getAdjacentProducts();

		$this->context->smarty->assign(array(
			'prev_product'=> $adjacent_products['previous'],
			'next_product'=> $adjacent_products['next']
		));

		parent::initContent();
	}	
}

Time to add our buttons! Before that, though, open the cache/ folder and erase class_index.php so that our overrides can take place!

Step 3 – Adding the new buttons to product.tpl

In this last stepm I will use the default template (as always), so your code might differ from mine, especially if you are using Prestashop 1.5, as I am using 1.6.

We first need to decide where the two buttons are going to sit. Ideally, I recommend adding them at the very top of the product page, so that they are easily and immediately accessible. Of course, any place is fine. Once you decide on position, open up product.tpl located in your theme’s folder.

For my position, the right spot is immediately before the following code, at the very beginning of the file:

	<div class="primary_block row">

Paste the following in:

<!-- Navigation -->

<div class="product-navigation clearfix" style="margin-bottom:20px">
	{if $prev_product}
		<a title="{$prev_product.name}" class="btn btn-default" href="{$link->getProductLink($prev_product.id_product, $prev_product.link_rewrite)}">{l s='Previous Product'}</a>
	{/if}
	{if $next_product}
		<a title="{$next_product.name}" class="btn btn-default" style="float:right"href="{$link->getProductLink($next_product.id_product, $next_product.link_rewrite)}">{l s='Next Product'}</a>
	{/if}
</div>

And we are done!

Display previous and next navigation buttons in the product page in prestashop

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

  • Doud26

    Perfect for me in PS 1.7.5.2 with override;)
    I just adjust the order field and way

  • Adam Uy

    Thank you for this simple yet very awesome tutorial, but the buttons doesn’t display. I put this {$prev_product|print_r} and it display ‘1’. and also the $next_product, why it doesn’t display?

  • Jakob

    Thanks for the tutorial! One thing I would add however is to check whether the product is active, if you have a bunch of disabled product you’ll get a “Product is no longer active” message when browsing products.

    Should work to just add “AND p.active = 1″ (without the quotation marks) to the end of lines 20 and 28 of override/classes/Product.php

    • NemoPS

      Nice addition, thanks!

  • Javier

    Thank you very much for your tut.
    Everything works fine, but, clicking to Quick View product the arrows are showed to navigate. In this case, it should not be present.

  • KevinNash

    Hello, that works well on PS1.5.4.1 but can’t we pick the actual category instead of the default one ?
    When a product is in differents category, that cause category change :(

    • NemoPS

      Yeah that’s an issue, I know, I guess it could work by using the cookie object to track your last visited category

      • KevinNash

        By the way, thank you for all your tips NemoPS, they are awesome :)

  • Spark111

    Problem with a wrong url / possible 404.
    Easy way out: In ProductController.php add:
    if (isset($this->product)) {
    etcetera.
    Does somebody has a better solution?

    Hope this helps.
    Thanks for the code. Saved me quite some time :)

  • desgnl

    it’s working perfectly. thank you!

  • NemoPS

    You have to add it before the ORDER clause, what you did is wrong in terms of SQL syntax ;)

  • Eric

    Thanks a lot ! I just add a ‘AND p.active=1′ in both mysql request, to be sure the product will be active.

  • Juan Antonio Meca Lopez

    Don’t work for me, i can’t see the buttons. I copy the override folder to my override but i don’t see anything. Should i do any more?
    Thank you very much for your help

    • Chacha

      Sorry Juan but Nemo will not answer you like me, 23 days and still waiting :)

      • NemoPS

        It’s not that I don’t want to answer, it’s just that I don’t have enough time to answer everyone. You can grab images by using $link->getImageLink.
        As for why it’s not working, those files are not meant to be plug an play. Clear cache, add what’s necessary to the tpl and they will appear for sure :) Tuts are made to be followed, not to provide a ready-to-go zip file :)

        • Chacha

          Nemo, nobody said: You don’t want to answer :)
          I understand that you do not have time.
          But the same “$link->getImageLink” is not enough. I need to type something in Product.php but I don’t what :(

        • Ziad

          As he said he can’t do everything for everyone. There’s a paid version available that provides images. Look it up else you’d better learn some PHP basics since you seem so inclined to tinker with the code. Once you’re familiar with it you’ll find some code in the same tpl file that uses getImageLink. You should be able to reuse it for your own purposes then.

        • jordi

          Tried in PS 1.5.4.1 and is not working, I’m sure I did all the steps correctly, so not sure what is the problem. Any hint ?

  • Chacha

    How to add img to prev and next products?

Store Top Sales

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