You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Magento 2如何编程递归将子分类产品分配至所有父分类

Recursive Parent Category Product Assignment for Magento 2.1.7

I get it—using the Anchor setting works for simple category trees, but when you've got deep nested categories like Home > Consumabile Auto & Moto > Lubrifianti > Uleiuri Motor > 0W-20, manually setting Anchor on every parent is a total pain. Let's build a custom solution that automatically assigns products to all parent categories whenever you add them to a child category.

Step 1: Create a Custom Module

First, we'll make a basic module called Custom_CategorySync. Here's the file structure you need:

app/code/Custom/CategorySync/
├── etc/
│   ├── module.xml
│   └── events.xml
├── Observer/
│   └── AssignParentCategories.php
└── registration.php

1.1 Module Registration (registration.php)

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Custom_CategorySync',
    __DIR__
);

1.2 Module Configuration (etc/module.xml)

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Custom_CategorySync" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

Step 2: Set Up the Event Observer

We'll listen to the catalog_product_category_save_after event, which triggers right after a product's category associations are saved.

etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_category_save_after">
        <observer name="custom_categorysync_assign_parent_categories" instance="Custom\CategorySync\Observer\AssignParentCategories"/>
    </event>
</config>

Step 3: Write the Recursive Assignment Logic

This observer will fetch all the child categories assigned to the product, then recursively traverse up each category's parent chain, adding the product to every parent category (if it's not already there).

Observer/AssignParentCategories.php

<?php
namespace Custom\CategorySync\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Catalog\Model\CategoryRepository;
use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\Exception\NoSuchEntityException;

class AssignParentCategories implements ObserverInterface
{
    protected $categoryRepository;
    protected $productRepository;

    public function __construct(
        CategoryRepository $categoryRepository,
        ProductRepository $productRepository
    ) {
        $this->categoryRepository = $categoryRepository;
        $this->productRepository = $productRepository;
    }

    public function execute(Observer $observer)
    {
        $product = $observer->getProduct();
        $productId = $product->getId();
        $currentCategoryIds = $product->getCategoryIds();
        $newCategoryIds = $currentCategoryIds;

        // Iterate through each category assigned to the product
        foreach ($currentCategoryIds as $categoryId) {
            try {
                $category = $this->categoryRepository->get($categoryId);
                // Recursively get all parent categories
                $parentCategories = $this->getAllParentCategories($category);
                
                foreach ($parentCategories as $parentCategory) {
                    $parentId = $parentCategory->getId();
                    // Add parent category ID if not already in the list
                    if (!in_array($parentId, $newCategoryIds)) {
                        $newCategoryIds[] = $parentId;
                    }
                }
            } catch (NoSuchEntityException $e) {
                // Skip invalid categories
                continue;
            }
        }

        // Only update if new categories were added
        if (count($newCategoryIds) !== count($currentCategoryIds)) {
            $product->setCategoryIds($newCategoryIds);
            $this->productRepository->save($product);
        }

        return $this;
    }

    /**
     * Recursively fetch all parent categories of a given category
     * @param \Magento\Catalog\Model\Category $category
     * @return array
     */
    protected function getAllParentCategories($category)
    {
        $parents = [];
        $parentId = $category->getParentId();

        // Stop when we reach the root category (ID 1)
        while ($parentId != 1) {
            try {
                $parentCategory = $this->categoryRepository->get($parentId);
                $parents[] = $parentCategory;
                $parentId = $parentCategory->getParentId();
            } catch (NoSuchEntityException $e) {
                break;
            }
        }

        return $parents;
    }
}

Step 4: Activate the Module

Run these commands via SSH to enable and set up the module:

php bin/magento module:enable Custom_CategorySync
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:clean

How It Works

  • When you save a product (or assign it to a new category), the observer triggers
  • It grabs all categories the product is already in
  • For each category, it climbs up the parent chain, collecting every parent category (stopping at the root)
  • It adds any missing parent category IDs to the product's category list
  • Finally, it saves the product with the updated category assignments

Notes

  • Avoid Duplicates: The code checks if the parent category is already assigned before adding it, so you won't get redundant entries
  • Bulk Operations: If you're assigning products in bulk, this will still work—just make sure to reindex after bulk saves if needed
  • Magento 2.1.7 Compatibility: This code uses classes and methods that are fully compatible with your version

内容的提问来源于stack exchange,提问作者Razvan Zamfir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:58:44