【问题标题】:Magento 2: Get Parent Category ID of Category IDMagento 2:获取类别 ID 的父类别 ID
【发布时间】:2020-03-05 13:31:22
【问题描述】:

如何在 Magento 2 中获取类别 ID 的父类别 ID?

在 Magento 1 中,我使用了以下方法:

$product_id = 101; //for example
$product = Mage::getModel('catalog/product')->load($product_id); //get product object by product ID
$category_ids = $product->getCategoryIds(); //array of all categories that the product is in
foreach ($category_ids as $cat_ids) {
    $parent_id = Mage::getModel('catalog/category')->load($cat_id)->getParentId(); //
    echo $parent_id; //outputs an int ID of parent category
}

在 Magento 2 中,我一直在尝试以下方法:

$product_id = 101; //again, for example
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$productRepository = $objectManager->create('\Magento\Catalog\Model\ProductRepository');
$product = $productRepository->getById($product_id); //get product object by product ID
$category_ids = $product->getCategoryIds(); //array of all categories that the product is in
foreach ($category_ids as $cat_ids) {
    echo $cat_ids;
}

到目前为止,我的代码运行良好,$category_ids 是产品所在的所有类别的数组。但是我无法弄清楚如何获取 $category_ids 中每个子类别 ID 的父类别 ID数组。

注意* 我知道我不应该正式直接使用 ObjectManager,所以请从你的答案中保存它。我正在寻求以这种方式专门使用 ObjectManager 来迭代 $category_ids 并为每个子类别 ID 加载父类别 ID。

【问题讨论】:

    标签: php magento magento2 magento-1.9


    【解决方案1】:

    像往常一样,有多种方法可以实现这一目标。

    CategoryFactory 路由

    要直接加载一个类别,您可以通过负责\Magento\Catalog\Model\Category 类的Factory Singleton 加载它。这是\Magento\Catalog\Model\CategoryFactory 类。从Category 的每个实例中,您可以简单地调用方法getParentId() 来获取父ID。

    foreach ($categoryIds as $categoryId) {
        try {
            $category = $this->_categoryFactory->create()->load($categoryId);
        } catch (\Exception $e) {
            /* Handle this appropriately... */
        }
        echo 'Parent Category ID: ', $category->getParentId(), PHP_EOL;
    }
    

    在本例中,$categoryIds 是您从 \Magento\Catalog\Model\Product 实例中提取的类别 ID 的 array

    CategoryRepository 路由

    或者最好您可以使用\Magento\Catalog\Model\CategoryRepository 类的单例实例作为Factory 的包装器。它将通过一些附加的错误处理来处理所有加载,它还将存储对加载类别的引用以供以后重用。因此,如果您在一次执行期间多次执行此操作,或者怀疑稍后将加载相同的类别,则使用 Repository 将优化您的性能。

    foreach ($categoryIds as $categoryId) {
        try {
            $category = $this->_categoryRepository->get($categoryId);
        } catch (\Exception $e) {
            /* Handle this appropriately... */
        }
        echo 'Parent Category ID: ', $category->getParentId(), PHP_EOL;
    }
    

    收集路线

    这应该是一条更快的路线,因为您 (1) 从数据库中加载所有类别一次,而不是在后端使用多个 sql 调用,并且 (2) 您可以控制 Category 中填充的内容,以及遗漏了什么。请注意,几乎只有您在addAttributeToSelect() 中输入的内容才会被填充到集合中。但如果你只是在parent_id 之后,这应该不是问题。

    首先,确保您是familiar with collections,然后为Magento\Catalog\Model\ResourceModel\Category\CollectionFactory 获取一个CollectionFactory Singleton,然后像这样填充它:

    /** @var \Magento\Catalog\Model\ResourceModel\Category */
    $collection = $this->_categoryCollectionFactory->create();
    
    # Specifically select the parent_id attribute
    $collection->addAttributeToSelect('parent_id');
    
    # Only select categories with certain entity_ids (category ids)
    $collection->addFieldToFilter('entity_id', ['in' => $categoryIds])
    
    # Iterate over results and print them out!
    foreach ($collection as $category) {
        echo 'Parent Category ID: ', $category->getParentId(), PHP_EOL;
    }
    

    然而,强大的力量伴随着巨大的风险。上面的代码将没有任何错误纠正。如果存在逻辑数据库错误,例如指向缺失类别的产品,则该类别将被从集合中省略,作为程序员的您将发现并处理它。此外,您必须自己决定如何通过对集合的过滤器来处理商店视图和活动/非活动类别。

    直接数据库路由

    好的,除非您确切地知道自己在做什么,并且迫切需要性能,否则我不会推荐这条路线。

    这会非常快,但是有各种各样的问题,比如依赖底层数据存储和数据结构,更不用说你对(非常不可能,公平地说)未来的底层更新持开放态度数据库结构,直接通过 Magento 升级或通过(讨厌的)第 3 方模块。更不用说 SQL 注入或 XSS 攻击的危险了。 (不过,您应该始终牢记这一点,使用所有 4 种方法。

    当您直接使用 ObjectManager 时,我假设您不会介意这些缺点,所以我想也给您这个选项。

    基本的伪sql是:

    select parent_id from <name of catalog_category_entity table> where entity_id in (<sanitized, comma-separated list of category ids);
    

    首先,获取\Magento\Framework\App\ResourceConnection 类的实例。您将使用它来获取catalog_category_entity 的必要表名,以及获取数据库连接。然后你应该清理你的数据,最后,绑定并执行查询并获取你的数据。

    /** @var \Magento\Framework\App\Connection */
    $connection = $this->_resourceConnection->getConnection();
    
    # Get prefixed table name of catalog_category_entity
    $categoryEntityTableName = $this->_resourceConnection->getTableName('catalog_category_entity');
    
    # Sanitize the $categoryIds array using a bit of overkill
    array_walk_recursive($categoryIds, function(&$value, $key){
        $value = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
    });
    
    # Prepare a sql statement which fetches entity_id and parent_id
    $preparedStatement = $this->connection->prepare('select entity_id, parent_id from ' . $categoryEntityTableName . ' where entity_id in (' . implode(',', array_fill(0, sizeof($categoryIds), '?')) . ')');
    
    # Bind sanitized $categoryIds array to statement and execute said statement in one single step 
    $preparedStatement->execute($categoryIds);
    
    # fetch result as a key-value pair array of entity_id=>parent_id
    $parentIds = $preparedStatement->fetchAll(\PDO::FETCH_KEY_PAIR);
    
    # Iterate over results and print them out!
    foreach ($parentIds as $categoryId => $parentId) {
        echo 'Parent Category ID: ', (int)$parentId, PHP_EOL;
    }
    

    脚注

    我假设您很清楚直接使用ObjectManager 的利弊,所以我就不再讲课了;-)。但是,为了将来参考,我还必须向偶然发现这个答案的未来读者说明,如果他们不知道如何获取 CategoryFactoryCategoryRepositoryCollectionFactoryResourceConnection 类的实例,我高度建议他们通过预期的Dependency Injection 机制这样做。

    【讨论】:

    • Aron,抱歉回复晚了。这个答案太全面了,我需要表示非常感谢!这无疑扩大了我对 Magento 的理解。我仍然是初学者,所以你的一些答案需要我进行额外的研究才能理解。这是我的工作代码:
    • ``` $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $productRepository = $objectManager->create('\Magento\Catalog\Model\ProductRepository'); $product = $productRepository->getById($product_id); $categoryIds = $product->getCategoryIds(); foreach($categoryIds as $catid) { $category = $objectManager->create('Magento\Catalog\Model\Category')->load($catid); $parent_id = $category->getParentId(); } ```
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2017-09-24
    • 2012-06-03
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多