How to show more products in the Prestashop Specials module

In today’s tutorial we will see how to display more discounted products in the Prestashop Specials Block module, by using a native function the software already provides.

Download Project Files
  • Version used: Prestashop 1.5.6

Introduction

Today will make use of the native getPricesDrop method the Product class kindly provides, to display as many discounted products we want in the sidebar block.

Note that unlike previous tutorials, we will now directly edit core files, so that even the beginner user can tag along without having to know how to create a module from scratch, or how to use overrides. Therefore, please note that the changes we are going to apply will be gone if you upgrade Prestashop. If you want to do it, be sure you keep a copy of the blockspecials folder, so that you can always paste it over the original one, once the upgrade is complete. Of course, there is a slight chance you will see small bugs pop out in this case.

The ‘cache’ problem and the default theme’s override

There are 2 preliminary things to mention: firstly, the Specials Block Module (named blockspecials) is cached. This means that our changes will not be reflected unless we clear smarty cache upon modifying it; secondly, if you use the default theme, the blockspecials module has a template file in the theme’s folder, which is the one we need to edit.

Now that we know this, let’s get started!

Modifying the Specials Block Module class

Reach out modules/blockspecials/ and open up blockspecials.php. Now locate the hookRightColumn method, which looks approximately like this (mine is taken from 1.5.6):


	public function hookRightColumn($params)
	{
		if (Configuration::get('PS_CATALOG_MODE'))
			return;
		
		// We need to create multiple caches because the products are sorted randomly
		$random = date('Ymd').'|'.round(rand(1, max(Configuration::get('BLOCKSPECIALS_NB_CACHES'), 1)));

		if (!Configuration::get('BLOCKSPECIALS_NB_CACHES') || !$this->isCached('blockspecials.tpl', $this->getCacheId('blockspecials|'.$random)))
		{
			if (!($special = Product::getRandomSpecial((int)$params['cookie']->id_lang)) && !Configuration::get('PS_BLOCK_SPECIALS_DISPLAY'))
				return;

			$this->smarty->assign(array(
				'special' => $special,
				'priceWithoutReduction_tax_excl' => Tools::ps_round($special['price_without_reduction'], 2),
				'mediumSize' => Image::getSize(ImageType::getFormatedName('medium')),
			));
		}

		return $this->display(__FILE__, 'blockspecials.tpl', $this->getCacheId('blockspecials|'.$random));
	}

Now, look closely at the following snippet

	$special = Product::getRandomSpecial((int)$params['cookie']->id_lang)

This is the code that grabs a single random discounted product. We need to replace this with another method, which instead grabs a list of discounted products.

Therefore, change the snippet into this:

	$specials = Product::getPricesDrop((int)$params['cookie']->id_lang, 0, 5)

Explanation: as mentioned at the beginning of the article, we are making use of the built-in function Prestashop already provides with the Product Class: getPricesDrop. This is called on the ‘price-drop’ page, and allows you to retrieve a list of all the currently active specials, with pagination. As we don’t need pagination, we use the second parameter to tell the method that we want to display page 0, and to grab 5 elements. Of course, feel free to grab as many as you want, by changing the last parameter.

At this point, as we also changed the variable name to specials to be more descriptive, we need to amend the following part as well:


		$this->smarty->assign(array(
			'special' => $special,
			'priceWithoutReduction_tax_excl' => Tools::ps_round($special['price_without_reduction'], 2),
			'mediumSize' => Image::getSize(ImageType::getFormatedName('medium')),
		));


So change special into specials, and get rid of the second element in the array, as it’s referring to a single product price


		$this->smarty->assign(array(
			'specials' => $specials,
			'mediumSize' => Image::getSize(ImageType::getFormatedName('medium')),
		));


At this point, the hookRightColumn method should look like this:

	public function hookRightColumn($params)
	{
		if (Configuration::get('PS_CATALOG_MODE'))
			return;
		
		// We need to create multiple caches because the products are sorted randomly
		$random = date('Ymd').'|'.round(rand(1, max(Configuration::get('BLOCKSPECIALS_NB_CACHES'), 1)));

		if (!Configuration::get('BLOCKSPECIALS_NB_CACHES') || !$this->isCached('blockspecials.tpl', $this->getCacheId('blockspecials|'.$random)))
		{
			if (!($specials = Product::getPricesDrop((int)$params['cookie']->id_lang, 0, 5)) && !Configuration::get('PS_BLOCK_SPECIALS_DISPLAY'))
				return;

			$this->smarty->assign(array(
				'specials' => $specials,
				'mediumSize' => Image::getSize(ImageType::getFormatedName('medium')),
			));

		}

		return $this->display(__FILE__, 'blockspecials.tpl', $this->getCacheId('blockspecials|'.$random));
	}

Now login to the back office, go to Advanced Parameters, Performance and hit the ‘Clear Smarty cache & Autoload cache’ button. Note that this button is not present if your Prestashop version is lower than 1.5.5. If this is the case, go to the cache/smarty/cache folder and delete blockspecials. If the folder is not there, delete everything but index.php.

Also, if your Prestashop version is quite old, you might need to go to tools/smarty/ to find the cache folder/

Editing the Specials Module Template

Okay, we have our discounted products list. However, if we now load the front page while the module is activated, we will receive an error, as it’s still referring to the old variable:

How to show more discounted products in blockspecials - error

Let’s take care of it. As mentioned at the beginning of the article, if you use the default theme you can reach themes/default/modules/blockspecials and edit blockspecials.tpl from there. If you don’t, check the presence of that file in your theme folder, and if it’s absent, open the original blockspecials.tpl found in the module folder (the same folder where we modified the .php file).

It should look approximately like this (again, Prestashop 1.5.6 here!):

{*
* 2007-2013 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <contact@prestashop.com>
*  @copyright  2007-2013 PrestaShop SA
*  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*}

<!-- MODULE Block specials -->
<div id="special_block_right" class="block products_block exclusive blockspecials">
	<p class="title_block"><a href="{$link->getPageLink('prices-drop')|escape:'html'}" title="{l s='Specials' mod='blockspecials'}">{l s='Specials' mod='blockspecials'}</a></p>
	<div class="block_content">

{if $special}
		<ul class="products clearfix">
			<li class="product_image">
				<a href="{$special.link|escape:'html'}"><img src="{$link->getImageLink($special.link_rewrite, $special.id_image, 'medium_default')|escape:'html'}" alt="{$special.legend|escape:html:'UTF-8'}" height="{$mediumSize.height}" width="{$mediumSize.width}" title="{$special.name|escape:html:'UTF-8'}" /></a>
			</li>
			<li>
				{if !$PS_CATALOG_MODE}
					{if $special.specific_prices}
						{assign var='specific_prices' value=$special.specific_prices}
						{if $specific_prices.reduction_type == 'percentage' && ($specific_prices.from == $specific_prices.to OR ($smarty.now|date_format:'%Y-%m-%d %H:%M:%S' <= $specific_prices.to && $smarty.now|date_format:'%Y-%m-%d %H:%M:%S' >= $specific_prices.from))}
							<span class="reduction"><span>-{$specific_prices.reduction*100|floatval}%</span></span>
						{/if}
					{/if}
				{/if}

					<p class="s_title_block"><a href="{$special.link|escape:'html'}" title="{$special.name|escape:html:'UTF-8'}">{$special.name|escape:html:'UTF-8'}</a></p>
				{if !$PS_CATALOG_MODE}
					<span class="price-discount">{if !$priceDisplay}{displayWtPrice p=$special.price_without_reduction}{else}{displayWtPrice p=$priceWithoutReduction_tax_excl}{/if}</span>
					<span class="price">{if !$priceDisplay}{displayWtPrice p=$special.price}{else}{displayWtPrice p=$special.price_tax_exc}{/if}</span>
				{/if}
			</li>
		</ul>
		<p>
			<a href="{$link->getPageLink('prices-drop')|escape:'html'}" title="{l s='All specials' mod='blockspecials'}">&raquo; {l s='All specials' mod='blockspecials'}</a>
		</p>
{else}
		<p>{l s='No specials at this time' mod='blockspecials'}</p>
{/if}
	</div>
</div>
<!-- /MODULE Block specials -->

The modification we need to apply can be done in a single step:


{*
* 2007-2013 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <contact@prestashop.com>
*  @copyright  2007-2013 PrestaShop SA
*  @license    http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*}

<!-- MODULE Block specials -->
<div id="special_block_right" class="block products_block exclusive blockspecials">
	<p class="title_block"><a href="{$link->getPageLink('prices-drop')|escape:'html'}" title="{l s='Specials' mod='blockspecials'}">{l s='Specials' mod='blockspecials'}</a></p>
	<div class="block_content">

{if $specials}
		<ul class="products clearfix">
			{foreach from=$specials item=special}
				<li>
					<a href="{$special.link|escape:'html'}"><img src="{$link->getImageLink($special.link_rewrite, $special.id_image, 'medium_default')|escape:'html'}" alt="{$special.legend|escape:html:'UTF-8'}" height="{$mediumSize.height}" width="{$mediumSize.width}" title="{$special.name|escape:html:'UTF-8'}" /></a>

					{if !$PS_CATALOG_MODE}
						{if $special.specific_prices}
							{assign var='specific_prices' value=$special.specific_prices}
							{if $specific_prices.reduction_type == 'percentage' && ($specific_prices.from == $specific_prices.to OR ($smarty.now|date_format:'%Y-%m-%d %H:%M:%S' <= $specific_prices.to && $smarty.now|date_format:'%Y-%m-%d %H:%M:%S' >= $specific_prices.from))}
								<span class="reduction"><span>-{$specific_prices.reduction*100|floatval}%</span></span>
							{/if}
						{/if}
					{/if}

						<p class="s_title_block"><a href="{$special.link|escape:'html'}" title="{$special.name|escape:html:'UTF-8'}">{$special.name|escape:html:'UTF-8'}</a></p>
					{if !$PS_CATALOG_MODE}
						<span class="price-discount">{if !$priceDisplay}{displayWtPrice p=$special.price_without_reduction}{else}{displayWtPrice p=$priceWithoutReduction_tax_excl}{/if}</span>
						<span class="price">{if !$priceDisplay}{displayWtPrice p=$special.price}{else}{displayWtPrice p=$special.price_tax_exc}{/if}</span>
					{/if}
				</li>
			{/foreach}
		</ul>
		<p>
			<a href="{$link->getPageLink('prices-drop')|escape:'html'}" title="{l s='All specials' mod='blockspecials'}">&raquo; {l s='All specials' mod='blockspecials'}</a>
		</p>
{else}
		<p>{l s='No specials at this time' mod='blockspecials'}</p>
{/if}
	</div>
</div>
<!-- /MODULE Block specials -->

Explanation: first, we refer to $specialsinstead of $special. Then, inside the <ul>, we add {foreach from=$specials item=special}, and close the loop right before the closing </ul>, so that everything inside will be valid for each of our special product. Then, we get rid of:

			<li class="product_image">
				<a href="{$special.link|escape:'html'}"><img src="{$link->getImageLink($special.link_rewrite, $special.id_image, 'medium_default')|escape:'html'}" alt="{$special.legend|escape:html:'UTF-8'}" height="{$mediumSize.height}" width="{$mediumSize.width}" title="{$special.name|escape:html:'UTF-8'}" /></a>
			</li>

And place”


<a class="product-img" href="{$special.link|escape:'html'}"><img src="{$link->getImageLink($special.link_rewrite, $special.id_image, 'medium_default')|escape:'html'}" alt="{$special.legend|escape:html:'UTF-8'}" height="{$mediumSize.height}" width="{$mediumSize.width}" title="{$special.name|escape:html:'UTF-8'}" /></a>

At the top of the remaining li item.

Save and refresh, you should get something like this:

How to show more products in the Prestashop specials block - list displayed

Last cosmetic touches

We have the list, but it looks ugly. Let’s make it at least decent! Back to the original blockspecials folder in modules/, open blockspecials.css

Locate and change this:

#special_block_right li.product_image {
	padding-right:10px;
	width:62px;
}

Into this

#special_block_right li .product-img {
	float: left;
	display:block;
	margin-right:10px;
	width:62px;
}

Then adjust the list element size by changing this:

#special_block_right .products li {
	padding:15px 0;
	width: 130px;
	border:none;
}

Into this

#special_block_right .products li {
	padding:15px 0;
	width: 100%;
	border:none;
	position:relative;
	border-bottom:1px dotted #ccc;
}

Modify the reduction label from this:

#special_block_right .products span.reduction {
	display:block;
	float:right;
	padding:0 0 0 10px;
	font-weight:bold;
	font-size:12px;
	color:#fff;
	background:url(img/bg_reduction.png) no-repeat 0 0
}

To this

#special_block_right .products span.reduction {
	display:block;
	position:absolute;
	right: 0;
	bottom: 30px;
	padding:0 0 0 10px;
	font-weight:bold;
	font-size:12px;
	color:#fff;
	background:url(img/bg_reduction.png) no-repeat 0 0
}

And lastly add the following at the end of the file:

#special_block_right .s_title_block, #special_block_right .price-discount, #special_block_right .price {
	float: left;
	display: block;
	width: 100px;
}

We are done!

How to show more products in the Prestashop specials block - Final Result

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

  • Riccardo Benaltrismo

    Hi, is there an updated version of this for ps 1.6~?

    Is there also possibile to select by ID which product are shown?

  • ilhwan cho

    Hi, Thank your fir your code. However, this is not working with me. Could you please help me to work this out?

    The PS version is 1.5.3.1

    I changed the code as provided and because the version does not have button to clear cache I manually delete all cache file except index.php

    When I load the modified blockspecial.php, the website does not show up anything.

    It is just a white page.

    To figure out the problem, I tried to delete some codes.

    // this line does not work
    return $this->display(__FILE__, ‘blockspecials.tpl’, $this->getCacheId(‘blockspecials|’.$random));

    // after deleting $this->getCacheId(‘blockspecials|’.$random));
    return $this->display(__FILE__, ‘blockspecials.tpl’);

    When I delete the $this-> getCachedID ~~~

    the website shows up, but does not working as I expected.

    Thank you in advance.

    • NemoPS

      Could you clarify “not working as expected”? Did you also clear the site’s cache?

      • ilhwan cho

        It supposed to show the special items on the special block. But If I load the modified file, only just white page that shows nothing is displayed.
        I did not clear the site’s cache, how can I clear it?

        • NemoPS

          You didn’t turn on error reporting :)

        • ilhwan cho

          Fatal error: Call to undefined method BlockSpecials::getCacheId() in modules/blockspecials/blockspecials.php on line 122

          I have this error message. Could you give me advice to fix this problem?

        • NemoPS

          Just get rid of that call :)

        • ilhwan cho

          When I delete that call, the website works fine but the special block does not show products….

        • ilhwan cho

          Oh it’s working now. I thought I deleted the call and didn’t work. But I tried to delete the call again now, it is working well. Thank a lot Nemo.

  • http://roythemes.com Roy Velvet

    Work on 1.6 too. Thank you.

  • Mike

    Could you please make an update for the boots tart 1.6 theme. This does not work on that. Fantastic tutorial please help.

  • Théo

    Thank you it works. But is it possible to put 3 random produtcs? Because it always shows the same 3 special products.

    • NemoPS

      You have to modify the getPricesDrop method for that, it doesn’t come with a native parameter to get random products!

  • Gabriel55

    Search in classes/Product.php fuction getRandomSpecial

    WHERE p.id_product = ‘.(int)$id_product.’
    GROUP BY product_shop.id_product';

    Replace whith

    WHERE p.id_product = ‘.(int)$id_product.’
    ORDER BY RAND()
    GROUP BY product_shop.id_product';

  • Tralala lululu

    Yes, just done straight thru copy/paste from this page, in 1.5.6.2. works nice of course as mentioned several times :) thank you <3

  • Nick

    Great article Nemo!
    It’s working nice except one thing,
    Notice: Undefined index: price_without_reduction in /home/mysite/public_html/modules/blockspecials/blockspecials.php on line 121

    That line says:
    ‘priceWithoutReduction_tax_excl’ => Tools::ps_round($specials[‘price_without_reduction’], 2),

    and i’m guessing now but maybe the getPricesDrop method doesn’t return this index.

    Hope to hear from you soon.

    Nick

    • Nick

      it was my mistake, i should have deleted that line.

      It works beautifully, it’s just that I want it to show random products from the specials category.
      Can you tell me how to modify the getPricesDrop() method so it gets random products? Or some other way to display just my couple of products?

      Thanks!

  • Gallo

    Done in 1.5.4.0!

    Thank you Sir!

  • john

    Hi ,

    thanks for that , doesn’t work properly in 1.5.6.1 maybe you could adjust it for new version ?

    thanks

    • http://nemops.com Nemo

      1.5.6.1 and 1.5.6 are almost identical, it works on the newest for sure, so you should check your code :)

      • jordi

        I’ve used this with PS 1.5.4.1, however, is showing to me the
        specials in “pairs” (2 columns), instead of just one by one. The problem
        is that is shows the image with the text below (product, disccounted
        product, disccount), but the text of one product in one column is too
        close to the text of the 2nd column product). What I’ve missed ? I’ve
        verified all the .php, .tpl and .csc changes and found not mistake …

  • http://metzon.nl harald

    good article, just keep in mind that if your theme has an override on the blockspecials module you should make the change there also!

Store Top Sales

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