Display product count in Subcategory menu


Magento is the most popular use for ecommerce solutions in the web, because there have already useful built in functions and modules such a newsletter sending, credit card payments, strong securities and more and make life easy as a magento developer.

In some our work projects, we need to add extra functionally in Magento Store, such a creating custom magento modules, creating custom widgets, add custom pages.


In this tutorial, I would like to share on how get the count of products in Subcategories in navigation and append the count in sub category name.

In the screenshot below, we appended the count of products in corresponding subcategories, this is very easy to add. This works in Magento Community Edition 1.7.0.2. and 1.8.1.0 However if Magento Community release the new version 1.9.x and up, I will update this post and test the compatibility of the module. So let’s start.

Preview

Get Product Count in Top Menu Subcategories

What will you do is go to the core directory

'\app\code\core\Mage\Page\Block\Html\Topmenu.php'

and copy the Topmenu.php, and create a override copy in local folder like

'\app\code\local\Mage\Page\Block\Html\Topmenu.php'

and modify it, just find the function ‘_getHtml’ and replace the function code below.

protected function _getHtml(Varien_Data_Tree_Node $menuTree, $childrenWrapClass)
{
        $html = '';

        $children = $menuTree->getChildren();
        $parentLevel = $menuTree->getLevel();
        $childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;

        $counter = 1;
        $childrenCount = $children->count();

        $parentPositionClass = $menuTree->getPositionClass();
        $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';

        foreach ($children as $child) {

            $child->setLevel($childLevel);
            $child->setIsFirst($counter == 1);
            $child->setIsLast($counter == $childrenCount);
            $child->setPositionClass($itemPositionClassPrefix . $counter);

            $outermostClassCode = '';
            $outermostClass = $menuTree->getOutermostClass();

            if ($childLevel == 0 && $outermostClass) {
                $outermostClassCode = ' ';
                $child->setClass($outermostClass);
            }

			/* custom code */
			$category = Mage::getModel('catalog/category')->load(str_replace('category-node-', '', $child->getId()));
			$prodCollection = Mage::getResourceModel('catalog/product_collection')->addCategoryFilter($category);
            /* custom code end */

			$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';

			/* original */
			// $html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml($child->getName()) . '</span></a>';

			/* custom count products */
			$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml($child->getName()) . (is_null($parentLevel) ? '' : ' ('.$prodCollection->count().')') . '</span>' . '</a>';

            if ($child->hasChildren()) {
                if (!empty($childrenWrapClass)) {
                    $html .= '<div>';
                }
                $html .= '<ul>';
                $html .=  $this->_getHtml($child , $childrenWrapClass);
                $html .= '</ul>';

                if (!empty($childrenWrapClass)) {
                    $html .= '</div>';
                }
            }
            $html .= '</li>';

            $counter++;
        }

        return $html;
}

Magento can be able to override the Block and Model local directory except to the Controller and Config. So in the Topmenu.php we modify the function ‘_getHtml’, we getting the sub category id via str replace and count. and after the just refresh the cache. It’s pretty easy If you enjoyed this article, please consider sharing it!

About Axl Mulat

Im Axl Mulat, WordPress and Magento Developer. I create in site (istockphp.com) to share what i learn in my web projects. Add me in Facebook, and , Linkedin.

  • http://blueclawecommerce.co.uk Johnboy

    A Better solution is to use an observer on page_block_html_topmenu_gethtml_before and you can then loop through all the menu nodes and change their name to add in the child count. That way you are much less likely to experience any conflicts with other modules or problems upgrading

    • http://istockphp.com admin

      i think my solution is fine. because i override the module in local folder, i won’t affect the update.

  • axlmulat

    thanks for the comment, ii work this.ill update later

  • axlmulat

    hi boris, sorry for late response, this is my solution, just replace the function _getHtml

    protected function _getHtml(Varien_Data_Tree_Node $menuTree, $childrenWrapClass)
    {
    $html = ”;

    $children = $menuTree->getChildren();
    $parentLevel = $menuTree->getLevel();
    $childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;

    $counter = 1;
    $childrenCount = $children->count();

    $parentPositionClass = $menuTree->getPositionClass();
    $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . ‘-’ : ‘nav-’;

    foreach ($children as $child) {

    $child->setLevel($childLevel);
    $child->setIsFirst($counter == 1);
    $child->setIsLast($counter == $childrenCount);
    $child->setPositionClass($itemPositionClassPrefix . $counter);

    $outermostClassCode = ”;
    $outermostClass = $menuTree->getOutermostClass();

    if ($childLevel == 0 && $outermostClass) {
    $outermostClassCode = ‘ class=”‘ . $outermostClass . ‘” ‘;
    $child->setClass($outermostClass);
    }

    /* custom code */
    $category = Mage::getModel(‘catalog/category’)->load(str_replace(‘category-node-’, ”, $child->getId()));
    $prodCollection = Mage::getResourceModel(‘catalog/product_collection’)->addCategoryFilter($category);
    if($prodCollection->count() != ’0′) {
    $count_child = ‘ (‘.$prodCollection->count().’)’;
    } else {
    $count_child = ”;
    }
    /* cuatom code end */

    $html .= ‘_getRenderedMenuItemAttributes($child) . ‘>’;

    /* original */
    // $html .= ‘getUrl() . ‘” ‘ . $outermostClassCode . ‘>’ . $this->escapeHtml($child->getName()) . ‘‘;

    /* custom count products */
    $html .= ‘getUrl() . ‘” ‘ . $outermostClassCode . ‘>’ . $this->escapeHtml($child->getName()) . (is_null($parentLevel) ? ” : $count_child) . ” . ‘‘;

    if ($child->hasChildren()) {
    if (!empty($childrenWrapClass)) {
    $html .= ”;
    }
    $html .= ”;
    $html .= $this->_getHtml($child , $childrenWrapClass);
    $html .= ”;

    if (!empty($childrenWrapClass)) {
    $html .= ”;
    }
    }
    $html .= ”;

    $counter++;
    }

    return $html;
    }