22

Is there a way to hide categories that don't have active products? Or, even better, only show categories that have active products and stock.

  • The question is whether this is a good idea. Users are confused when they change the menu. – MiMo Jan 23 '13 at 12:49
11

The easiest way to do this is to only rewrite the Mage_Catalog_Block_Navigation block:

=> In the method _renderCategoryMenuItemHtml() you want to replace the loop

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

=> with this:

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

=> and similarly in the method renderCategoriesMenuHtml() replace the code

 foreach ($this->getStoreCategories() as $child) {
        if ($child->getIsActive()) {
            $activeCategories[] = $child;
        }
    }

=> with this:

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

=> Finally add the method we were just using in our code:

protected function _hasProducts($category_id) {
    $products = Mage::getModel('catalog/category')->load($category_id)
        ->getProductCollection()
        ->addAttributeToSelect('entity_id')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4);
    return ( $products->count() > 0 )  ? true : false;
}

Bear in mind that the method checks each category individually by using the catalog/category model. So, if you have many categories, you might want to rewrite the code to not run into performance issues. In a smaller store we are running, this works fine.

  • Is it possible to box this up into an extension that can be dropped in to local folder? Worried about the code being overwritten in future Magento updates. – MagentoMac Nov 3 '13 at 18:11
10

There is no built-in feature for hiding empty categories (but you can manually select Is active = No for each category in admin area->catalog->manage categories)

Here is a link on a great post from Josh Prattski's blog, where he wrote step-by-step walkthrough on how-to make an extension for this purpose.

  • This looks good, but for whatever reason isn't working in our store... any ideas how to debug? Not getting any error messages. Followed the instructions to a tee, but no change in frontend. Have already disabled, then re-enabled compiler, and cleared cache etc. – MagentoMac Nov 3 '13 at 18:10
4

If you just want to hide them in the catalog navigation you could add an if condition in the template to check for amount of products in that category.

4

Maybe this would help too.

Go to the backend of your webshop.

Then to Catalog > Category > Manage Category, choose your category, and select the Display settings tab.

The label Display Mode could be set to

Show static block only.

4

To hide an empty category from Top menu, do the following:

Go to app/code/core/Mage/Catalog/Block Folder and copy Navigation.php.

Override Navigation.php in your local package. Open Navigation.php of your package and paste the following code in this file:

if ($category->getIsActive()) {
    $cat = Mage::getModel('catalog/category')->load($category->getId());
    $products = Mage::getResourceModel('catalog/product_collection')->addCategoryFilter($cat);

    Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
    Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products);
    Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($products);

    if (count($products) == 0) {
        return;
    }
}
  • Where in that file? – MarkE Jul 26 at 20:07
3

What worked for me is to create a template category tree and implement a condition function which renders the category tree:

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

    protected function _hasProducts($category_id) {
    $products = Mage::getModel('catalog/category')->load($category_id)
        ->getProductCollection()
        ->addAttributeToSelect('entity_id')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4);
    return ( $products->count() > 0 )  ? true : false;
}
2

You can execute following sql to disable all categories without products.

UPDATE `catalog_category_entity_int` AS `status`
INNER JOIN `eav_attribute` AS `attr` ON `attr`.`attribute_code` = 'is_active'
AND `attr`.`entity_type_id` = 3
AND `status`.`attribute_id` = `attr`.`attribute_id`
SET `status`.`value` = IF((SELECT COUNT(`index`.`product_id`)
    FROM `catalog_category_product_index` AS `index`
    WHERE `index`.`category_id` = `status`.`entity_id` GROUP BY `index`.`category_id`) > 0, 1, 0)
WHERE `status`.`store_id` = 0

More details you can find here http://quicktips.ru/all/hide-all-categories-without-products-and-show-categories-with-pr/

2

what I've did to hide empty categories is to rewrite Mage_Catalog_Model_Resource_Category_Tree load() function. I've to join product collection with category collection like below.

    $collection = Mage::getResourceModel('catalog/product_collection');
    Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($collection);
    Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);

 $collection->getSelect()->join(
        array('product_category' => Mage::getSingleton('core/resource')->getTableName('catalog/category_product_index')),
        'product_category.product_id = e.entity_id',
        array('')
    );
    $collection->getSelect()->where('product_category.category_id = '.$this->_table.'.entity_id');
    $select->columns(array('product_count' => $collection->getSelectCountSql()));

add this code before $arrNodes = $this->_conn->fetchAll($select); this line.

And wrap this code with this condition, this class called from frontend and backend model also

  if(!Mage::getSingleton('admin/session')->isLoggedIn())

I've added extra field product_count which contains actual active product count.

I am using a 3rd party module to display category on the top menu and I've put condition based on product count when the menu is rendered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.