Display Product Rating in the Products List in Prestashop

Regardless of what we sell, it’s always a good idea to showcase how much our products are loved by our customers. Prestashop comes with a review module, but the rating only displays in the product page. Let’s see how to show the product rating in the products list too!

  • Version used: Prestashop 1.5.4
  • Product Comments Module: version 2.3

Introduction

It’s vital for every shop to let customers know about the experience of people who previously bought there. It’s the essence of e-commerce, and people tend to trust more a shop whose customers review those products they bought, If they’re happy with them. Thus, it’s becoming more and more important to have some kind of review system.
Prestashop comes with the so-known “Prestashop Product comments” module, which adds a basic review system to our store. The problem with this is that it’s only displaying reviews (and, subsequently, ratings) in the product detail page. In this tutorial, we will modify the existing module to allow it to hook to product listings, thus enabling each page displaying products to also have those nice stars displayed. Here is the result we want to achieve:

Prestashop product rating in Products List - End result

Step 1 – Adding a new hook to the Product Rating module

In order to display those cute stars in the product list, we need a new hook. This hook will be placed right below the product name in the list, but to begin with, let’s open up modules/productcomments/productcomments.php, and find the install() method.

	public function install()
	{
		if (!file_exists(dirname(__FILE__).'/'.self::INSTALL_SQL_FILE))
			return false;
		else if (!$sql = file_get_contents(dirname(__FILE__).'/'.self::INSTALL_SQL_FILE))
			return false;
		$sql = str_replace(array('PREFIX_', 'ENGINE_TYPE'), array(_DB_PREFIX_, _MYSQL_ENGINE_), $sql);
		$sql = preg_split("/;\s*[\r\n]+/", trim($sql));

		foreach ($sql as $query)
			if (!Db::getInstance()->execute(trim($query)))
				return false;
		if (parent::install() == false ||
			!$this->registerHook('productTab') ||
			!$this->registerHook('extraProductComparison') ||
			!$this->registerHook('productTabContent') ||
			!$this->registerHook('header') ||
			!$this->registerHook('productOutOfStock') ||
			!Configuration::updateValue('PRODUCT_COMMENTS_MINIMAL_TIME', 30) ||
			!Configuration::updateValue('PRODUCT_COMMENTS_ALLOW_GUESTS', 0) ||
			!Configuration::updateValue('PRODUCT_COMMENTS_MODERATE', 1))
				return false;
		return true;
	}

We want to add our new hook there, so let’s do it right after registering the productOutOfStock hook:

	public function install()
	{
		if (!file_exists(dirname(__FILE__).'/'.self::INSTALL_SQL_FILE))
			return false;
		else if (!$sql = file_get_contents(dirname(__FILE__).'/'.self::INSTALL_SQL_FILE))
			return false;
		$sql = str_replace(array('PREFIX_', 'ENGINE_TYPE'), array(_DB_PREFIX_, _MYSQL_ENGINE_), $sql);
		$sql = preg_split("/;\s*[\r\n]+/", trim($sql));

		foreach ($sql as $query)
			if (!Db::getInstance()->execute(trim($query)))
				return false;
		if (parent::install() == false ||
			!$this->registerHook('productTab') ||
			!$this->registerHook('extraProductComparison') ||
			!$this->registerHook('productTabContent') ||
			!$this->registerHook('header') ||
			!$this->registerHook('productOutOfStock') ||
			!$this->registerHook('productInList') ||
			!Configuration::updateValue('PRODUCT_COMMENTS_MINIMAL_TIME', 30) ||
			!Configuration::updateValue('PRODUCT_COMMENTS_ALLOW_GUESTS', 0) ||
			!Configuration::updateValue('PRODUCT_COMMENTS_MODERATE', 1))
				return false;
		return true;
	}

As you noticed, we added !$this->registerHook(‘productInList’) ||. This will be the name of our new hook.
Reset or install the module, then place a couple of comments and give them some different star rating. be sure they appear in the product page.

Step 2 – Adding the hook to the product list template

Open up product-list.tpl, which can be found in themes/nameofyourtheme folder. I will be using the default 1.5.4 Template for this example.

Locate the product name, which should be around line 44:

	<h3><a href="{$product.link|escape:'htmlall':'UTF-8'}" title="{$product.name|escape:'htmlall':'UTF-8'}">{$product.name|escape:'htmlall':'UTF-8'|truncate:35:'...'}</a></h3>

After it, add the following snippet:

	{hook h='productInList' idproduct=$product.id_product}

Explanation: we are taking advantage of a new way to add hooks, which was introduced in Prestashop 1.5 (To learn more: Adding new hooks to prestashop (the new way)). We can pass any number of arguments to the parameters of the hook, and in this case I chose to pass the product id, which is available to us since we are right inside the products iteration function (foreach loop).

Step 3 – Creating the hooking function

So, we have our hook. Let’s test it out. At the end of productcomments.php create a new function, as such:

	function hookProductInList($params)
	{
		echo 'hey there';
	}

Save & refresh, and you should get this:

Prestashop product rating in Products List - New hook in action

If you can’t see it, go back and check the previous steps, as it means the hook is not being processed. if it is, move forward and change the lastly created function this way:

	function hookProductInList($params)
	{
		require_once(dirname(__FILE__).'/ProductComment.php');
		require_once(dirname(__FILE__).'/ProductCommentCriterion.php');

		$id_product = $params['idproduct'];
		$product_average = 0;

		$grades = ProductComment::getAveragesByProduct($id_product, $this->context->language->id);
		$criterions = ProductCommentCriterion::getByProduct($id_product, $this->context->language->id);
		$grade_total = 0;
	}

Explanation: First, we need the ProductComment and ProductCommentCriterion classes, and we include them at the beginning of the method. Then, we define the product id as a variable, to avoid accessing the huge params array every time. Lastly, we get all the average grades for the product and all the criterions, and set a default value for the total grade, to avoid undeclared variable issues. Let’s go ahead and calculate the average grade for every product.

After the previous code, add the following:

		if (count($grades) > 0)
		{
			foreach ($criterions as $criterion)
			{
				if (isset($grades[$criterion['id_product_comment_criterion']]))
				{
					$grade_total += (float)($grades[$criterion['id_product_comment_criterion']]);
				}
			}

			$product_average = $grade_total / count($criterions);
		}

Explanation: We check that we actually have grades, and then, for each criterion, if the grades array contains something for that criterion, we add it to the total. In this stage, we are building the sum of all grades. After looping through all the criterions, we get the total average dividing the total grade by the number of criterions. This way we are sure the final average is the “average of all averages” of all criterions.

As a final step in this function, let’s assign the number we just got, and return a template:


		$this->context->smarty->assign('average_total', (int)$product_average);
		return $this->display(__FILE__, '/product-list.tpl');

We want to get the integer part of the average so be sure to add (int) when assigning it. We don’t have the mentioned product-list.tpl template file in the module’s folder, let’s create it in the last step!

Step 4 – Creating a template file to display the rating

Create a new .tpl file in modules/productcomments and call it product-list.tpl. Be sure it has the .tpl extension. if you don’t know how to create one from scratch, copy and rename one of the files which are in the folder, and delete everything it contains. Open up the new file and add the following:

	<div class="star_content clearfix">
	{section name="i" start=0 loop=5 step=1}
		{if $smarty.section.i.index lt $average_total}
                        <div class="star star_on"><a href=""></a></div>
		{else}
			<div class="star"><a href=""></a></div>
		{/if}
	{/section}
	</div>

We are simply taking advantage of the section helper that smarty provides, allowing us to iterate a block of code for a defined number of times; in this case, 5. Inside the loop, we check the average total for the product. If it’s bigger than the current iteration index, it means the current star element must be active, if not, it must be grayed out. Save and refresh, you should get something like this:

Prestashop product rating in Products List - Almost Finished

Messy. Let’s clean it up a bit. Go to your theme folder and open up css/product_list.css. Locate #product_list li h3.

	#product_list li h3 {
		padding:0 0 10px 0;
		font-size:13px;
		color:#000
	}

Change that padding to 0. All of it. Then, add the following at the end of the file (or where you want actually, it doesn’t matter):

#product_list li .star_content
{
	display: inline-block;
	margin-bottom: 10px;
}

Save and refresh. We are done! This is the end result. As you can see, the current product rating is now displaying correctly below each name:

Prestashop product rating in Products List - End result

Need Prestashop Modules? Have a look at my Prestashop Addons Store!

Looking for quality PrestaShop Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , | Posted under PrestaShop | RSS 2.0

Author Spotlight

Fabio Porta

Fabio Porta

Fabio has been involved in web development and design since 2005, when launched his first website at the age of 16. He’s now highly skilled in both client and server side development, along with design, and since August 2012 runs a successful website about PrestaShop tutorials and Prestashop Modules called Nemo’s Post Scriptum, at http://nemops.com

One Comment on Display Product Rating in the Products List in Prestashop

  1. Deli-Cart says:

    Nice function, at step 3 the description however is not perfect. After getting error messages for half an hour, I’ve figured out that it’s not enough to just copy-paste the published code in the same order but they also have to be within the same function (within the same {} section). Otherwise it doesn’t work, well, at least doesn’t work on 1.5.2. Maybe just make step 3 a little bit more clear. But otherwise nice and working! Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *


4 + 6 =

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>