Skip to content

Magento – only show categories containing products in main navigation

I was speaking to a client in Bristol who needed a freelance Magento developer to make some changes to their site. Top of the list was to modify the main navigation so that a category would only show if it contained active products, or sub categories with active products.

To cut a very long story short, if you override or subclass Mage_Catalog_Block_Navigation you can do this fairly quickly. Add the method _hasProducts as shown below, then you need to call this inside the renderCategoriesMenuHtml() and _renderCategoryMenuItemHtml() methods…

/**
* Check if a product has an active products
* @param int $category_id
* @return boolean
*/
private function _hasProducts( $category_id )
{
$products = Mage::getModel('catalog/category')->load($category_id)
->getProductCollection()
->addAttributeToSelect('entity_id')
->addAttributeToFilter('status', 1)
->addAttributeToFilter('visibility', 4);
/* @var $products Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
return ( $products->count() > 0 )  ? true : false;
}

Then modify the 2 methods below…

protected function _renderCategoryMenuItemHtml()
{
//snip a whole load of code until you reach the first foreach loop
foreach ($children as $child) {
if ( $child->getIsActive() ) {
if( $child->hasChildren() ) {
$activeChildren[] = $child;
}else{
if( $this->_hasProducts( $child->entity_id ) ) {
$activeChildren[] = $child;
}
}
}
//don't change the rest of the method...
}

public function renderCategoriesMenuHtml()
{
//snip a whole load of code until you reach the first foreach loop
foreach ($this->getStoreCategories() as $child) {
/* @var $child Varien_Data_Tree_Node */
if ( $child->getIsActive() ) {
if( $child->hasChildren() ) {
$activeCategories[] = $child;
}else{
if( $this->_hasProducts( $child->entity_id ) ) {
$activeCategories[] = $child;
}
}
}
}
//don't change the rest of the method...

}

Looking for a Magento developer to help you get your ecommerce website moving? Sweet-Apple is based near Bath and builds and supports cost effective Magento ecommerce websites. Give us a call on 01380 830224 – we’d love to help.

This entry was posted in Magento. Bookmark the permalink.

2 Responses to Magento – only show categories containing products in main navigation

  1. Thanks for this solution, a couple of hours of research and I found this!! Very useful for what I was after. I made a slight amendment though and just changed this line in both the functions. Which checks the product count at the same time as getIsActive().

    FROM

    foreach ($children as $child) {
    if ($child->getIsActive()) {
    $activeChildren[] = $child;
    }
    }

    TO

    foreach ($children as $child) {
    if ($child->getIsActive() && $this->_hasProducts($child->entity_id)) {
    $activeChildren[] = $child;
    }
    }

  2. Hi Craig.

    Nice! I’d forgotten that the second condition on the if statement wouldn’t run if the first failed, hence was trying to save a database call. You code’s clearer and more readable.