4

I have a category structure like this with a total of around 5000 categories:

  • A is_active=1
    • A1 is_active=1
      • A1-1 is_active=1
      • A1-2 is_active=1
      • A1-...
    • A2
    • A3
  • B is_active=0
    • B1 is_active=1
      • B1-... is_active=1
    • B2
    • B3

...

Now, getting all active categories is quite easy:

/** @var \Mage_Catalog_Model_Resource_Category_Collection $categories */
            $categories = Mage::getResourceModel('catalog/category_collection');

            $categories->addAttributeToSelect('*');
            $categories->addAttributeToFilter('entity_id', ['neq' => $this->getCurrentCategory()->getId()]);
            $categories->addAttributeToFilter('is_active', 1);


            return $categories;

I obviously also get all the B1 subcategories; how do I remove those from the returned collection? In general: I want to remove all the categories with a disabled parent from the collection. My hunch is to make a loop, but I suspect there is a smarter solution.

7

Yes, there are smarter solutions that perform better: First of all, each category has an attribute "path" that could be used to filter things in a smart way. You can add a filter like this:

    $categories->addAttributeToFilter('path', array('like' => '1/3/%');

The path includes the ID 1 (left part in example) and the Root Catalog of your Store (3 in the example).

An alternative is to create the other collection first ($excludeCategories) and convert them to a list of IDs:

$excludeIds = $excludeCategories->getAllIds();

Next, you can use these IDs to exclude from the original collection:

$categories->addAttributeToFilter('entity_id', array('nin', $excludeIds));

In the example above, "nin" stands for "NOT IN".

EDIT: Based on the suggestion of @Amasty I'm happy to share a bit more direct solution. If you want to prevent any category from being loaded that has a parent that is inactive, the goal is first to find all those parents:

$inactive = Mage::getModel('catalog/category')->getCollection();
$inactive->addAttributeToFilter('is_active', 0);
$inactiveIds = $inactive->getAllIds();

Next, with this list of inactive parents ($inactiveIds) you can find all categories that do not have those inactive parents in their paths:

$categories = Mage::getModel('catalog/category')->getCollection();
$categories->addAttributeToFilter('is_active', 1);
foreach($inactiveIds as $inactiveId) {
    $categories->addAttributeToFilter('path', array('nlike' => '%/'.$inactiveId.'/%'));
}

This worked for me in a demo Magento environment. However, I'm not sure how well this is going to perform with 5000 categories. It simply depends on how many of these categories are inactive and how many are not. Most likely you will want to have the output of things cached properly.

  • not sure it answers the original question. We need to exclude an active category that have one of inactive parent. – Amasty Feb 13 '15 at 10:49
0
$categories = Mage::getModel('catalog/category')
        ->getCollection()
        ->addAttributeToSelect('entity_id') 
        ->addAttributeToSelect('name')      
        ->addAttributeToSelect('parent_id')     
        ->addAttributeToSelect('url_path')
        ->addAttributeToSelect('request_path')
        ->addAttributeToSelect('include_in_menu')
        ->addAttributeToSelect('*')
        ->addAttributeToFilter('level',array('in' => array(3,4)))
        ->addAttributeToFilter('path',array('like' => $_category->getPath().'%'))
        ->addAttributeToSort('position', 'ASC')       
        ->addAttributeToFilter('is_active', 1);

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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