Displaying Product Count and Price Ranges for subcategories in PrestaShop and ThirtyBees

In this quick tutorial, you will learn how to add the product count, as well as the price ranges, for subcategories in PrestaShop and Thirtybees, to give your customer a better understanding of your catalog.

This Tutorial works with ThirtyBees as well!

Step 1 – Retrieving the product count for each subcategory

As always, the best approach when adding new functionalities to PrestaShop is to use overrides. Let’s add a new one for the Category class, which includes the function that retrieves subcategories in PrestaShop.

Create a new file named Category.php inside override/classes, and open it up in your favorite code editor. Then, let’s start by adding some simple override code, inside php tags:

class Category extends CategoryCore
{
}

We want to extend the method named getSubcategories, and even if it should be the same across the last PrestaShop version, it’s always best to copy your own, from the original Category.php. Mine, from PrestaShop 1.6.1.15, looks like this:

    public function getSubCategories($id_lang, $active = true)
    {
        $sql_groups_where = '';
        $sql_groups_join = '';
        if (Group::isFeatureActive()) {
            $sql_groups_join = 'LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`)';
            $groups = FrontController::getCurrentCustomerGroups();
            $sql_groups_where = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '='.(int)Group::getCurrent()->id);
        }

        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
		SELECT c.*, cl.id_lang, cl.name, cl.description, cl.link_rewrite, cl.meta_title, cl.meta_keywords, cl.meta_description
		FROM `'._DB_PREFIX_.'category` c
		'.Shop::addSqlAssociation('category', 'c').'
		LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = '.(int)$id_lang.' '.Shop::addSqlRestrictionOnLang('cl').')
		'.$sql_groups_join.'
		WHERE `id_parent` = '.(int)$this->id.'
		'.($active ? 'AND `active` = 1' : '').'
		'.$sql_groups_where.'
		GROUP BY c.`id_category`
		ORDER BY `level_depth` ASC, category_shop.`position` ASC');

        $formated_medium = ImageType::getFormatedName('medium');

        foreach ($result as &$row) {
            $row['id_image'] = (Tools::file_exists_cache(_PS_CAT_IMG_DIR_.(int)$row['id_category'].'.jpg') || Tools::file_exists_cache(_PS_CAT_IMG_DIR_.(int)$row['id_category'].'_thumb.jpg')) ? (int)$row['id_category'] : Language::getIsoById($id_lang).'-default';
            $row['legend'] = 'no picture';
        }
        return $result;
    }

Paste the whole method into our new override.
The next step is actually retrieving the product count itself. We are going to instantiate a new category object for each subcategory, so you might want to consider an alternative way in case you have many (more than 10).
In the last foreach loop, after the “no picture” part, add the following:

class Category extends CategoryCore
{
    $category = new Category($row['id_category']);
    $row['product_count'] = $category->getProducts($id_lang, 1, 0, null, null, true);
}

As simple as that. We first instantiate the category object, give then id we got out of the loop, and then use the builtin getProducts method, passing in true as sixth parameter, in order to get the total number of products for that category.
Please notice that instanciating several objects might be resource-intensive, a note of caution must be considered, again, if you have a large number of subcategories.

Retrieving the price span for a certain category in PrestaShop

This part is optional, as it requires the Layered Navigation Module to be installed. If you are not using it, you can simply install, then disable it.
However, before proceeding, make sure you have your prices indexed in the module, by clicking the link shown in the next screenshot:

PrestaShop and Thirtybees layered price indexation

Now that we have everything set, it’s time to get to coding. The process is a little annoying, and what we can get with this method is just an approximation of the price, which is what is stored in the layered navigation basically. If you need a better range, like when you use psychological pricing, you might have to store minimum and maximum prices yourself, using an alternative way.
First, we retrieve a list of the product IDs for the current subcategory, and if we have any, we clean up the result array, so that each value is a simple number, and not another array:

if(!$row['product_count'])
    continue; // if no products, skip to the next subcategory
$product_ids = $this->getProductsWs();
// this would return products as array, with id => # as structure
// and therefore needs a cleanup
if($product_ids)
{
    foreach ($product_ids as $product) {
        $product_ids_clean[] = $product['id'];
    }
}

Lastly, we can simply add the following query to our previous code, just after the one we used to get the product count:

$row['price_span'] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
    SELECT MIN(price_min) as min_price, MAX(price_max) as max_price
    FROM '._DB_PREFIX_.'layered_price_index
    WHERE price_min > 0 AND id_product IN ('.implode(',', $product_ids_clean).')
    ');

We are using this query to retrieve the minimum and maximum prices of the shop’s subcategory we are currently viewing, making sure the minimum price is not zero.

Before proceeding at this point, since we used an override, it’s necessary to erase the class_index.php file, located in the cache/ folder, so that our override can be loaded and seen by PrestaShop.

Displaying the product count and price range for subcategories, in the PrestaShop default template

The last thing we have to do is add the stuff we just retrieved to the template.
Let’s open up category.tpl, located in the theme folder. The structure will vary a lot depending on your own theme, as for this example I will use the default-bootstrap that comes with PrestaShop 1.6. The standard theme for ThirtyBees is quite similar to it, so the same principles apply to that.

Locate the subcategories loop in the template:

{foreach from=$subcategories item=subcategory}

And make sure you stay inside it with any code we will write now. Where to add the snippet is entirely up to you, I chose the very end of the block, right before the closing LI element.

{foreach from=$subcategories item=subcategory}

...

    <p>{$subcategory.product_count} {l s='Products'}</p>
    {if $subcategory.product_count}
        <p>{displayPrice price=$subcategory.price_span.min_price} - {displayPrice price=$subcategory.price_span.max_price}</p>
    {/if}
    
</li>
{/foreach}

And that’s basically it. However, in the default PrestaShop template subcategories have a fixed height, and we need to account for that. Open up category.css, located in the theme folder /css, find the #subcategories ul li selector, and change its height to at least 260px (around line 50):

#subcategories ul li {
    float: left;
    width: 145px;
    margin: 0 0 13px 33px;
    text-align: center;
    height: 260px;
}

We are done, here is how it should display in the default-bootstrap theme of PrestaShop 1.6.

Price range and product count in PrestaShop and ThirtyBees Subcategories

p.s. You will notice it’s reading 1 Products. I didn’t add any extra code to keep it slim, but you might if you run a small shop with products that only have one product.

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

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