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.
2 Responses to Magento – only show categories containing products in main navigation
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;
}
}
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.