Have you ever used a standard PrestaShop Product Comments module? This module allows website visitors to post comments about products.
But this module has a very essential drawback: it lacks of pagination for product comments. To show how it works, let’s write a simple script that will create 100 comments for the first product. (Read the entire post. Below we’ve hidden a free module that enables pagination for product comments…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
require(dirname(__FILE__).'/config/config.inc.php'); for($i=0; $i<100; $i++){ Db::getInstance()->AutoExecute(_DB_PREFIX_.'product_comment', array( 'id_product' => '1', 'id_customer' => '3', 'id_guest' => '0', 'title' => 'Auto comment', 'content' => 'This source file is subject to the Open Software License (OSL 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/osl-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 [email protected] so they can send you a copy immediately.', 'customer_name' => 'A. Simonchik', 'grade' => '0', 'validate' => '1', 'deleted' => '0', 'date_add' => date('Y-m-d H:i:s') ), 'INSERT'); } |
We name file autoComment.php and put it into root PrestaShop category. When you click the link http://YOUR_STORE/autoComment.php, you will see 100 newly created fake comments for the first product.
Let’s start with finding the hook that is responsible for displaying comments. This is hookProductTabContent hook with the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public function hookProductTabContent($params) { global $smarty, $cookie; $id_guest = (!$id_customer = (int)$cookie->id_customer) ? (int)$cookie->id_guest : false; $customerComment = ProductComment::getByCustomer((int)(Tools::getValue('id_product')), (int)$cookie->id_customer, true, (int)$id_guest); //getting comments for a customer, it determines whether a customer writes a comment too early or not $averages = ProductComment::getAveragesByProduct((int)Tools::getValue('id_product'), (int)$cookie->id_lang); //getting criteria for product evaluation $averageTotal = 0; foreach ($averages AS $average) $averageTotal += (float)($average); $averageTotal = count($averages) ? ($averageTotal / count($averages)) : 0; //product average point $smarty->assign(array( 'logged' => (int)$cookie->id_customer, 'action_url' => '', 'comments' => ProductComment::getByProduct((int)Tools::getValue('id_product')), 'criterions' => ProductCommentCriterion::getByProduct((int)Tools::getValue('id_product'), (int)$cookie->id_lang), 'averages' => $averages, 'product_comment_path' => $this->_path, 'averageTotal' => $averageTotal, 'allow_guests' => (int)Configuration::get('PRODUCT_COMMENTS_ALLOW_GUESTS'), 'too_early' => ($customerComment AND (strtotime($customerComment['date_add']) + Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME')) > time()), 'delay' => Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME'))); $controller = new FrontController(); $controller->pagination((int)ProductComment::getCommentNumber((int)Tools::getValue('id_product'))); return ($this->display(__FILE__, '/productcomments.tpl')); } |
We are focused on performance of ProductComment::getByProduct function, because it returns all comments that are related to a product. Open ProductComment.php file, located in the module root, and look for the getByProduct function code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/** * Get comments by IdProduct * * @return array Comments */ public static function getByProduct($id_product, $p = 1, $n = null) { if (!Validate::isUnsignedId($id_product)) die(Tools::displayError()); $validate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); $sort_direction = Configuration::get('BELVG_COMMENTS_SORT_DIRECTION'); // a new parameter, responsible for sorting direction $p = (int)($p); $n = (int)($n); if ($p <= 1) $p = 1; if ($n != null AND $n <= 0) $n = 5; return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT pc.`id_product_comment`, IF(c.id_customer, CONCAT(c.`firstname`, \' \', LEFT(c.`lastname`, 1)), pc.customer_name) customer_name, pc.`content`, pc.`grade`, pc.`date_add`, pc.title FROM `'._DB_PREFIX_.'product_comment` pc LEFT JOIN `'._DB_PREFIX_.'customer` c ON c.`id_customer` = pc.`id_customer` WHERE pc.`id_product` = '.(int)($id_product).($validate == '1' ? ' AND pc.`validate` = 1' : '').' ORDER BY pc.`date_add` '.($sort_direction == 1 ? ' DESC ' : ' ASC ' ).' '.($n ? 'LIMIT '.(int)(($p - 1) * $n).', '.(int)($n) : '')); } |
Notice that the query has LIMIT parameter, but because optional parameters n and p are not transmitted, it is ignored when forming a line with sql-query. Well, then we should transmit them and for that purpose we create tpl-templates, containing the required logic, and put them in YOUR_STORE_DIR/themes/YOUR_THEME/modules/productcomments. This action will minimize changes in existing (original) module files as far as the file from a module folder is in a priority load.
We need to create several files: productcomments.tpl (modified standard template), pagination_comments.tpl (new template, responsible for pagination for comments) and ajax_load_content.tpl (it contains content, returned by ajax request).
Code of productcomments.tpl file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
<div id="idTab5"> <script type="text/javascript" src="{$module_dir}js/jquery.rating.pack.js"></script> <script type="text/javascript"> $(function(){literal}{{/literal} $('input[@type=radio].star').rating(); {literal}}{/literal}); $(function(){literal}{{/literal} $('.auto-submit-star').rating({literal}{{/literal} callback: function(value, link){literal}{{/literal} {literal}}{/literal} {literal}}{/literal}); {literal}}{/literal}); //close comment form function closeCommentForm(){ldelim} $('#sendComment').slideUp('fast'); $('input#addCommentButton').fadeIn('slow'); {rdelim} </script> <div id="ajax_comment_content"> {if $comments} {if $criterions|@count > 0} <h2>{l s='Average grade' mod='productcomments'}</h2> <div style="float: left"> {l s='Average' mod='productcomments'}:<br /> {section loop=6 step=1 start=1 name=average} <input class="auto-submit-star" disabled="disabled" type="radio" name="average" {if $averageTotal|round neq 0 and $smarty.section.average.index eq $averageTotal|round}checked="checked"{/if} /> {/section} </div> <div style="float: left; margin-left: 40px; width: 400px"> {foreach from=$criterions item=c} <div style="float: left; margin-left: 20px; margin-bottom: 10px;"> {$c.name|escape:'html':'UTF-8'}<br /> {section loop=6 step=1 start=1 name=average} <input class="auto-submit-star" disabled="disabled" type="radio" name="{$c.name|escape:'html':'UTF-8'}_{$smarty.section.average.index}" value="{$smarty.section.average.index}" {if isset($averages[$c.id_product_comment_criterion]) AND $averages[$c.id_product_comment_criterion]|round neq 0 AND $smarty.section.average.index eq $averages[$c.id_product_comment_criterion]|round}checked="checked"{/if} /> {/section} </div> {/foreach} </div> {/if} <div class="comment-bottom"> <div class="title-header allComments"> {include file="$tpl_dir./modules/productcomments/pagination_comments.tpl"} </div> <div class="clear table_block"> <ul class="comment-list"> {foreach from=$comments item=comment} <li id="product_comment_{$comment.id_product_comment|intval}"> <div class="title-header"> <h3 class="title">{$comment.customer_name|escape:'html':'UTF-8'}</h3> <p class="comments-total">{dateFormat date=$comment.date_add|escape:'html':'UTF-8' full=0}</p> </div> <p>{$comment.content|escape:'html':'UTF-8'|nl2br}</p> </li> {/foreach} </ul> </div> </div> {else} <p class="align_center">{l s='No customer comments for the moment.' mod='productcomments'}</p> {/if} {if $too_early == true} <p class="align_center">{l s='You should wait' mod='productcomments'} {$delay} {l s='second(s) before posting a new comment' mod='productcomments'}</p> {elseif $cookie->isLogged() == true || $allow_guests == true} <p class="align_center"><input style="margin:auto;" class="button_large" type="button" id="addCommentButton" value="{l s='Add a comment' mod='productcomments'}" onclick="$('#sendComment').slideDown('slow');$(this).slideUp('slow');" /></p> <form action="{$action_url}" method="post" class="std" id="sendComment" style="display:none;"> <fieldset> <p class="align_right"><a href="javascript:closeCommentForm()">X</a></p> <p class="bold">{l s='Add a comment' mod='productcomments'}</p> {if $criterions|@count > 0} <table border="0" cellspacing="0" cellpadding="0"> {section loop=$criterions name=i start=0 step=1} <tr> <td> </td> <td> <input type="hidden" name="id_product_comment_criterion_{$smarty.section.i.iteration}" value="{$criterions[i].id_product_comment_criterion|intval}" /> {$criterions[i].name|escape:'html':'UTF-8'} </td> <td> </td> <td> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" id="{$smarty.section.i.iteration}_grade" value="1" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="2" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="3" checked="checked" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="4" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="5" /> </td> </tr> {/section} </table> {/if} {if $allow_guests == true && $cookie->isLogged() == false}<p><label for="customer_name">{l s='Your name:' mod='productcomments'}</label><input type="text" name="customer_name" id="customer_name" /></p>{/if} <p><label for="comment_title">{l s='Title:' mod='productcomments'}</label><input type="text" name="title" id="comment_title" /></p> <p><label for="content">{l s='Comment:' mod='productcomments'}</label><textarea cols="46" rows="5" name="content" id="content"></textarea></p> <p class="submit"> <input class="button" name="submitMessage" value="{l s='Send' mod='productcomments'}" type="submit" /> </p> </fieldset> </form> {else} <p class="align_center">{l s='Only registered users can post a new comment.' mod='productcomments'}</p> {/if} </div> {literal} <script> $('#pagination_next a, #pagination_previous a, a.pagination_page_number').live("click", function(){ $.ajax({ url: "{/literal}{$base_dir}{literal}modules/productcomments/ajax_load.php", type: "POST", data: {p : $(this).attr('rel'), id_product : $('input[name="id_product"]').val()}, beforeSend: function() { backup_content = $("#ajax_comment_content").html(); $("#ajax_comment_content").slideUp('4000').empty(); $('#ajax_comment_content').append('<img src="{/literal}{$base_dir}{literal}modules/productcomments/img/pagination-loader.gif" />').slideDown('2000'); }, success: function( html ){ $("#ajax_comment_content").empty(); $("#ajax_comment_content").append(html); }, error: function ( jqXHR, textStatus, errorThrown ){ alert('something went wrong...'); $("#ajax_comment_content").html( backup_content ); } }); return false; }) </script> {/literal} </div> |
In this file we have changed js-code that transfers ajax-request to the modules/productcomments/ajax_load controller with parameters p – the page number and id_product. Also we call pagination_comments.tpl {include file = “$ tpl_dir. /Modules/productcomments/pagination_comments.tpl”} in this file. Don’t forget to put pagination-loader.gif file into modules/productcomments /img folder, which will be displayed during the ajax-request.
PrestaShop Modules
Take your store to the next level with PrestaShop modules from BelVG
Visit the storeThe code of pagination_comments.tpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
{if isset($no_follow) AND $no_follow} {assign var='no_follow_text' value='rel="nofollow"'} {else} {assign var='no_follow_text' value=''} {/if} {if isset($p) AND $p} {assign var='requestPage' value=$link->getPaginationLink(false, false, false, false, true, false)} {assign var='requestNb' value=$link->getPaginationLink(false, false, true, false, false, true)} <!-- Pagination --> <div id="pagination" class="pagination"> {if $start!=$stop} <ul class="pagination"> {if $p != 1} {assign var='p_previous' value=$p-1} <li id="pagination_previous"><a {$no_follow_text} rel="{$p_previous}" class="pagination_page_number" href="{$link->goPage($requestPage, $p_previous)}">« {l s='Previous' mod='productcomments'}</a></li> {else} <li id="pagination_previous" class="disabled"><span>« {l s='Previous' mod='productcomments'}</span></li> {/if} {if $start>3} <li><a {$no_follow_text} rel="1" class="pagination_page_number" href="{$link->goPage($requestPage, 1)}">1</a></li> <li class="truncate">...</li> {/if} {section name=pagination start=$start loop=$stop+1 step=1} {if $p == $smarty.section.pagination.index} <li class="current"><span>{$p|escape:'htmlall':'UTF-8'}</span></li> {else} <li><a {$no_follow_text} rel="{$smarty.section.pagination.index}" class="pagination_page_number" href="{$link->goPage($requestPage, $smarty.section.pagination.index)}">{$smarty.section.pagination.index|escape:'htmlall':'UTF-8'}</a></li> {/if} {/section} {if $pages_nb>$stop+2} <li class="truncate">...</li> <li><a rel="{$pages_nb}" class="pagination_page_number" href="{$link->goPage($requestPage, $pages_nb)}">{$pages_nb|intval}</a></li> {/if} {if $pages_nb > 1 AND $p != $pages_nb} {assign var='p_next' value=$p+1} <li id="pagination_next"><a class="pagination_page_number" {$no_follow_text} rel="{$p_next}" href="{$link->goPage($requestPage, $p_next)}">{l s='Next' mod='productcomments'} »</a></li> {else} <li id="pagination_next" class="disabled"><span>{l s='Next' mod='productcomments'} »</span></li> {/if} </ul> {/if} </div> <!-- /Pagination --> {/if} |
The most crucial points here are transfer of parameters in rel page numbers you are planning to move to and pagination_page_number class for elements, displaying page numbers to move to.
In our ajax-request there is a file that a standard module doesn’t have. It is ajax_load.php with the content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?php require(dirname(__FILE__).'/../../config/config.inc.php'); include(dirname(__FILE__).'/../../init.php'); global $cookie, $smarty; require_once(dirname(__FILE__).'/ProductComment.php'); require_once(dirname(__FILE__).'/ProductCommentCriterion.php'); // enabling classes to work with comments $n = abs((int)(Tools::getValue('n', Configuration::get('BELVG_COMMENTS_PER_PAGE')))); $p = abs((int)(Tools::getValue('p', 1))); $id_product = abs((int)(Tools::getValue('id_product'))); $id_guest = (!$id_customer = (int)$cookie->id_customer) ? (int)$cookie->id_guest : false; $customerComment = ProductComment::getByCustomer($id_product, (int)$cookie->id_customer, true, (int)$id_guest); $nbComments = count(ProductComment::getByProduct((int)($id_product))); $range = 2; /* how many pages around page selected */ if ($p > (($nbComments / $n) + 1)) Tools::redirect(preg_replace('/[&?]p=\d+/', '', $_SERVER['REQUEST_URI'])); $pages_nb = ceil($nbComments / (int)($n)); $start = (int)($p - $range); if ($start < 1) $start = 1; $stop = (int)($p + $range); if ($stop > $pages_nb) $stop = (int)($pages_nb); $smarty->assign(array( 'allow_guests' => (int)Configuration::get('PRODUCT_COMMENTS_ALLOW_GUESTS'), 'comments' => ProductComment::getByProduct((int)($id_product), $p, $n), 'p' => (int)$p, 'n' => (int)$n, 'criterions' => ProductCommentCriterion::getByProduct((int)($id_product), (int)($cookie->id_lang)), 'nbComments' => (int)(ProductComment::getCommentNumber((int)($id_product))), 'action_url' => '', 'too_early' => ($customerComment AND (strtotime($customerComment['date_add']) + Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME')) > time()), 'range' => $range, 'start' => $start, 'stop' => $stop, 'pages_nb' => $pages_nb, )); $rendered_content = $smarty->fetch(_PS_ROOT_DIR_.'/modules/productcomments/ajax_load_content.tpl'); echo $rendered_content; ?> |
The content of ajax_load_content.tpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
{if $comments} {if $criterions|@count > 0} <h2>{l s='Average grade' mod='productcomments'}</h2> <div style="float: left"> {l s='Average' mod='productcomments'}:<br /> {section loop=6 step=1 start=1 name=average} <input class="auto-submit-star" disabled="disabled" type="radio" name="average" {if $averageTotal|round neq 0 and $smarty.section.average.index eq $averageTotal|round}checked="checked"{/if} /> {/section} </div> <div style="float: left; margin-left: 40px; width: 400px"> {foreach from=$criterions item=c} <div style="float: left; margin-left: 20px; margin-bottom: 10px;"> {$c.name|escape:'html':'UTF-8'}<br /> {section loop=6 step=1 start=1 name=average} <input class="auto-submit-star" disabled="disabled" type="radio" name="{$c.name|escape:'html':'UTF-8'}_{$smarty.section.average.index}" value="{$smarty.section.average.index}" {if isset($averages[$c.id_product_comment_criterion]) AND $averages[$c.id_product_comment_criterion]|round neq 0 AND $smarty.section.average.index eq $averages[$c.id_product_comment_criterion]|round}checked="checked"{/if} /> {/section} </div> {/foreach} </div> {/if} <div class="comment-bottom"> <div class="title-header allComments"> {include file="$tpl_dir./modules/productcomments/pagination_comments.tpl"} </div> <div class="clear table_block"> <ul class="comment-list"> {foreach from=$comments item=comment} <li id="product_comment_{$comment.id_product_comment|intval}"> <div class="title-header"> <h3 class="title">{$comment.customer_name|escape:'html':'UTF-8'}</h3> <p class="comments-total">{dateFormat date=$comment.date_add|escape:'html':'UTF-8' full=0}</p> </div> <p>{$comment.content|escape:'html':'UTF-8'|nl2br}</p> </li> {/foreach} </ul> </div> </div> {else} <p class="align_center">{l s='No customer comments for the moment.' mod='productcomments'}</p> {/if} {if $too_early == true} <p class="align_center">{l s='You should wait' mod='productcomments'} {$delay} {l s='second(s) before posting a new comment' mod='productcomments'}</p> {elseif $cookie->isLogged() == true || $allow_guests == true} <p class="align_center"><input style="margin:auto;" class="button_large" type="button" id="addCommentButton" value="{l s='Add a comment' mod='productcomments'}" onclick="$('#sendComment').slideDown('slow');$(this).slideUp('slow');" /></p> <form action="{$action_url}" method="post" class="std" id="sendComment" style="display:none;"> <fieldset> <p class="align_right"><a href="javascript:closeCommentForm()">X</a></p> <p class="bold">{l s='Add a comment' mod='productcomments'}</p> {if $criterions|@count > 0} <table border="0" cellspacing="0" cellpadding="0"> {section loop=$criterions name=i start=0 step=1} <tr> <td> </td> <td> <input type="hidden" name="id_product_comment_criterion_{$smarty.section.i.iteration}" value="{$criterions[i].id_product_comment_criterion|intval}" /> {$criterions[i].name|escape:'html':'UTF-8'} </td> <td> </td> <td> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" id="{$smarty.section.i.iteration}_grade" value="1" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="2" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="3" checked="checked" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="4" /> <input class="star" type="radio" name="{$smarty.section.i.iteration}_grade" value="5" /> </td> </tr> {/section} </table> {/if} {if $allow_guests == true && $cookie->isLogged() == false}<p><label for="customer_name">{l s='Your name:' mod='productcomments'}</label><input type="text" name="customer_name" id="customer_name" /></p>{/if} <p><label for="comment_title">{l s='Title:' mod='productcomments'}</label><input type="text" name="title" id="comment_title" /></p> <p><label for="content">{l s='Comment:' mod='productcomments'}</label><textarea cols="46" rows="5" name="content" id="content"></textarea></p> <p class="submit"> <input class="button" name="submitMessage" value="{l s='Send' mod='productcomments'}" type="submit" /> </p> </fieldset> </form> {else} <p class="align_center">{l s='Only registered users can post a new comment.' mod='productcomments'}</p> {/if} |
Ecommerce Development
Take your online store to the next level with BelVG Ecommerce Development
Visit the pageLast thing we need to do is to add changes into hookProductTabContent() function in order to transfer n and p parameters into query.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public function hookProductTabContent($params) { global $smarty, $cookie; $id_guest = (!$id_customer = (int)$cookie->id_customer) ? (int)$cookie->id_guest : false; $customerComment = ProductComment::getByCustomer((int)(Tools::getValue('id_product')), (int)$cookie->id_customer, true, (int)$id_guest); $averages = ProductComment::getAveragesByProduct((int)Tools::getValue('id_product'), (int)$cookie->id_lang); $averageTotal = 0; foreach ($averages AS $average) $averageTotal += (float)($average); $averageTotal = count($averages) ? ($averageTotal / count($averages)) : 0; $n = abs((int)(Tools::getValue('n', Configuration::get('BELVG_COMMENTS_PER_PAGE')))); // if the n parameter is not transferred, take the values если параметр n не передан, то значение берется из БД $p = abs((int)(Tools::getValue('p', 0))); // if the p parameter is not transferred, value equals zero $smarty->assign(array( 'logged' => (int)$cookie->id_customer, 'action_url' => '', 'comments' => ProductComment::getByProduct((int)Tools::getValue('id_product'), $p, $n), 'criterions' => ProductCommentCriterion::getByProduct((int)Tools::getValue('id_product'), (int)$cookie->id_lang), 'averages' => $averages, 'product_comment_path' => $this->_path, 'averageTotal' => $averageTotal, 'allow_guests' => (int)Configuration::get('PRODUCT_COMMENTS_ALLOW_GUESTS'), 'too_early' => ($customerComment AND (strtotime($customerComment['date_add']) + Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME')) > time()), 'delay' => Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME'))); $controller = new FrontController(); $controller->pagination((int)ProductComment::getCommentNumber((int)Tools::getValue('id_product'))); return ($this->display(__FILE__, '/productcomments.tpl')); } |
That’s it. Now your page with comments looks this way:<
In the module sources we used the parameter, responsible for sorting direction. It is considered in the query while getting comments for a product (BELVG_COMMENTS_SORT_DIRECTION).
Based on explanations above, we made pagination_for_product_comments module that you may easily download. To install it successfully, you need to replace the productcomments folder, containing a standard module, and put the folder with changed templates into your theme.
PrestaShop Development
Take your online store to the next level with BelVG PrestaShop development
Visit the page
Good info. Lucky me I recently found your site by accident.
I have bookmarked it for later!
hi alex, I realy need to pagination for prestashop 1.6, can help me?
Bobz,
We already have certain plans about future articles, but we will definitely keep your suggestions in mind about optimizing this article for the version 1.6
Thanks for sharing this one! It’s working great on previous version of PS. Just wondering, how to do this in prestashop 1.6? Im planning to update.
I wrote this article for v1.4, but I think that you can do it on the analogy of this, because modules don’t really change from version to version.
Thank you a lot!
Is it compatible with the 1.5.6.2 release of prestashop?
wow…. amazing ! thanks a lot
Danni,
Thanks for reading the article. It should be a default PrestaShop behavior for product comments, but unfortunately it’s not yet.
Great work ! This should become a default prestashop behavior for product comments. Thanks !!