1

Let's say I have a simple categories tree like this one :

  • Category 1
    • Subcategory 1.1
    • Subcategory 1.2
    • ...
    • Subcategory 1.675

Some products should be visible for all subcategories, without having to manually select the 675 subcategories. I'd like to only assign these products to Category 1. Then, when I go to Subcategory 1.675 page, I should see products directly assigned to Subcategory 1.675, but also those assigned to Category 1.

How to get this behavior ? A module, or some custom code to change product listing query ?

4 Answers 4

1
+50

I think an optimal solution for this would entail that a product collection for a given subcategory includes products belonging to its parent category, if the subcategory is flagged to allow such behavior.

Essentially, it comes down to adding an additional category (parent) filter to the product collection when you're on category 1.675, so that products in both 1 and 1.675 show up on. Here are the steps.

  1. Create a category yes/no attribute. Something like include_parent_products/"Include parent products on display?". Once added, go to the category manage page for 1.675 and flag it yes.
  2. Rewrite Mage_Catalog_Model_Layer::getProductCollection to load a modified collection if setting in step 1 is true.

    $displayParentProducts = $this->getCurrentCategory()->getIncludeParentProducts();
    if ($displayParentProducts) {
        $collection = $this->getCurrentCategory()->getProductCollectionIncludingParents();
    } else {
        $collection = $this->getCurrentCategory()->getProductCollection();
    }
    
  3. Rewrite/Create a new method Mage_Catalog_Model_Category::getProductCollectionIncludingParents.

    public function getProductCollection()
    {
        $parentCategory = ...; // Find parent category
        $collection = Mage::getResourceModel('catalog/product_collection')
            ->setStoreId($this->getStoreId())
            ->addCategoryFilter($this)
            ->addCategoryFilter($parentCategory)
            ;
        return $collection;
    }
    

With the above completed, category 1.675 will now display its products and its parent's as well.

2
  • 1
    Thanks dude, I've been able to get te desired behavior by doing what you say. I didn't implement the flag because I don't need it on my project, but I'll do it if needed.
    – OlivierH
    Mar 24, 2016 at 12:42
  • Right on! Yeah, the yes/no flag is entirely optional and depends on your shop's needs.
    – laketuna
    Mar 24, 2016 at 14:12
2

I don't think that something to change the listing query would be the best solution here. For sure it will add an overhead.
I think a better approach would be to create an observer that assigns automatically the products to all categories.
Case 1:
You want all the products from category 1 to be assigned to all subcategories:

Add a category yes/no attribute called show_products_in_child_categories (or find something shorter).
Create an observer on the catalog_category_save_after. If the category being saved has this attribute set to yes, assign all its products to all it's subcategories.

public function saveCategory($observer)
{
    $category = $observer->getEvent()->getCategory();
    if ($category->getShowProductsInChildCategories()) {
        $childrenIds = Mage::getResourceModel('catalog/category')->getChildrenIds($category, false);
        $productIds = $category->getProductCollection()->getAllIds();
        //for performance reasons you can insert directly in the table `catalog_category_product` each combination of $childrenIds X $productIds skipping the existing ones. 
        //Use `INSERT ... ON DUPLICATE KEY UPDATE...`.
    }
}

Add an observer on catalog_product_save_after that checks if the categories the product is on has that attribute set to yes. If so, assign it to subcategories.

Case 2.
Only some products from category 1 should end up on all subcategories.

Put a yes/no attribute on the products. assign_to_subcategories.
Then do the same thing as above, but filter the products on the category save observer by this attribute ->addAttributeToFilter('assign_to_subcategories', 1).

Sorry, I don;t have a fully working solution. Just an idea that should get you where you need to go.

3
  • Nice approach, but your solution require to save the parent category (Category 1) every time a subcategory is created. In my case, the client will make his subcategories list evolve during the time and I can't ask him to do this additional step.
    – OlivierH
    Mar 24, 2016 at 12:49
  • Then refer to case 2. You can add an observer on the product save event.
    – Marius
    Mar 24, 2016 at 12:56
  • Yes, this could be a working solution. If I eventually need a more flexible behavior, I'll implement this. Thanks.
    – OlivierH
    Mar 24, 2016 at 13:04
0

Place the following code into template sidebar

<?php
$currentCat = Mage::registry('current_category');

if ( $currentCat->getParentId() == Mage::app()->getStore()->getRootCategoryId() )

//Display current category
echo $this->getCurrentCategory()->getName() ;

else

{
// Display ParentCategory of Current Category
echo $this->getCurrentCategory()->getParentCategory()->getName() ;
}
?>

To display Sub Category of current Parent category Again for those wanting subcategories of the current page, use the following code: e.g.: /app/design/frontend/default/yourtemplatefolder/template/catalog/navigation/leftnav.phtml

<?php
    $currentCat = Mage::registry('current_category');

    if ( $currentCat->getParentId() == Mage::app()->getStore()->getRootCategoryId() )
    {
        // current category is a toplevel category
        $loadCategory = $currentCat;
    }
    else
    {

        $loadCategory = Mage::getModel('catalog/category')->load($currentCat->getParentId());
    }
    $subCategories = explode(',', $loadCategory->getChildren());

    foreach ( $subCategories as $subCategoryId )
    {
        $cat = Mage::getModel('catalog/category')->load($subCategoryId);

        if($cat->getIsActive())
        {
            echo '<a href="'.$cat->getURL().'">'.$cat->getName().'</a>';
        }
    }
?>
1
  • The matter is to modify the list of products displayed on category page, not to display a category tree.
    – OlivierH
    Mar 24, 2016 at 12:44
0

I would suggest use create an custom method to retrieve category_products. There are native mysql methods to solve this. here is an example Query.

SELECT p.* from catalog_category_entity as e
INNER JOIN catalog_category_product as cp on e.entity_id = cp.category_id
INNER JOIN catalog_product_entity as p ON cp.product_id = p.entity_id
WHERE e.`entity_id` IN (SELECT REPLACE(path,'/',',') FROM catalog_category_entity where entity_id = 65)

In the last Part, replace the 65 with the category id where you are in.

1
  • Yes, but should I use this query into Magento ? And shouldn't we use Magento standard API as in @musicliftsme answer, instead of directly querying db ?
    – OlivierH
    Mar 24, 2016 at 12:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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