5

How to get child categories from selected parent category when "Use Flat Catalog Category" is enabled?

I need to create a small menu which displays all sub-categories of current category in a custom menu.

To get sub-categories of the current category, I extended class Magento\Catalog\Block\Navigation and created a method which returns sub-categories (identifier of the current category is passed in $parent parameter):

namespace Company\MyNav\Block;
class MyNav extends \Magento\Catalog\Block\Navigation
{
    public function getCategoryChildren($parent)
    {
        $category = ObjectManager::getInstance()->create('Magento\Catalog\Model\Category');
        $subCategories = $category->getCategories($parent);
        return $subCategories;
    }
    // ...
}

It all works great, method getCategories from Magento\Catalog\Model\Category returns all sub-categories (also from all lower levels) of the selected parent category.

But as soon as I enable "Use Flat Catalog Category" option in admin, method getCategories returns entire tree of categories instead of only the children of the selected category.

  1. Shouldn't the same code give the same results no matter if flat categories are enabled or disabled? Is this a bug in Magento 2?

  2. Are there any additional steps needed to make this code work even flat categories field is enabled?

3

4 Answers 4

5
+50

You can use getChildren to get child category data in your block even Use Flat Catalog Category is enabled.

For example

namespace Custom\Module\Block\World;
class Index extends \Magento\Framework\View\Element\Template
{
    protected $_categoryFactory;
    protected $_category;
    protected $_categoryHelper;
    protected $_categoryRepository;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Helper\Category $categoryHelper,
        \Magento\Catalog\Model\CategoryRepository $categoryRepository,        
        array $data = []
    )
    {
        $this->_categoryFactory = $categoryFactory;        
        parent::__construct($context, $data);
    }
        /**
     * Get category object
     * Using $_categoryFactory
     *
     * @return \Magento\Catalog\Model\Category
     */
    public function getCategory($categoryId) 
    {
        $this->_category = $this->_categoryFactory->create();
        $this->_category->load($categoryId);        
        return $this->_category;
    }


    /**
     * Retrieve children ids comma separated
     *
     * @return string
     */
    public function getChildren($categoryId = false)
    {
        if ($this->_category) {
            return $this->_category->getChildren();
        } else {
            return $this->getCategory($categoryId)->getChildren();
        }        
    }  



}

Inside the phtml template.

$test =  $block->getChildren('20');
echo "<pre>";
print_r($test);

Out put

enter image description here

Reference link for more details.

Recommended to pass classes to constructor as a dependency.

Hope it helps.

2

You have use CategoryRepository for getting all categories with sub-categories.

$parentCatId = 1;
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$categoryRepository = $objectManager->create('Magento\Catalog\Model\CategoryRepository');
$parentcategories = $categoryRepository->get($parentCatId);
$categories = $parentcategories->getChildrenCategories();
foreach($categories as $category){
     $ChildCategoryValue[] = ['label' => $category->getName(), 'value' => $category->getId()];
}
return $ChildCategoryValue;

May be it will help you, thanks.

0
0

In Magento 1.x we can achieve the same thing with the help of recursive function. If you want to create menu in tree structure you have to use the same logic to achieve that.

So in Magento 2.x you can use the same logic of recursive function to achieve this thing with the help of Magento 2.x code.

$websiteRoorCategory = 2; // You have to set website root category id here
$ChildCategoryValue = getCategory($websiteRoorCategory);
echo '<pre>';print_r($ChildCategoryValue);


function getCategory($parentCatId)
{
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // Call object manager from class object
    $categoryRepository = $objectManager->create('Magento\Catalog\Model\CategoryRepository');
    $parentcategories = $categoryRepository->get($parentCatId);
    $categories = $parentcategories->getChildrenCategories();
    $i=0;
    foreach($categories as $category){
        $ChildCategoryValue[$i] = ['label' => $category->getName(), 'value' => $category->getId()];
        $childCat = getCategory($category->getId());
        if($childCat){
            $ChildCategoryValue[$i]['child'] = $childCat;
        }   
    $i++;
    }

    return $ChildCategoryValue;

}
0

Below code is used when flat_category enable from admin with current category get child category.

app/code/Test/Categorytree/view/frontend/templates/listing.phtml

<?php
    $currentCategory = $this->getCurrentCategoryInfo();
    $noOfCategory  = count($currentCategory);
?>
<?php if($noOfCategory) { ?>
<ul class="listing-category-manual">
<?php
    foreach($currentCategory as $categoryDetails){
        $categoryId = $categoryDetails->getId();
        $categoryObj = $this->getCategoryData($categoryId); 
        $categoryUrl = $categoryObj->getUrl();
        $categoryName = $categoryDetails->getName();        
 ?>
     <li class="listing-item">
            <div class="product details product-item-details">
                <a href="<?php echo $categoryUrl; ?>">       
                    <div class="listing-category-info">
                        <span class="category-name"><?php echo $categoryName; ?></span>
                    </div>
                </a>
            </div>
            <?php 
                $getSubCategory = $this->subCategory($categoryObj->getId());
                if(count($getSubCategory) > 0){
            ?>
                    <ul>
                    <?php foreach($getSubCategory as $subcat){  
                            $subId = $subcat['entity_id'];
                            $subcategoryObj = $this->getCategoryData($subId);
                            $categoryUrl = $subcategoryObj->getUrl();
                            $categoryName = $subcategoryObj->getName();
                    ?>
                    <li>
                       <a href="<?php echo $categoryUrl; ?>">  
                        <div class="listing-category-info">
                            <span class="category-name"><?php echo $categoryName; ?></span>
                        </div>
                        </a>
                    </li>
                    <?php } ?>
                    </ul>
            <?php } ?>
    </li> 
<?php   } //endforeach ?>
</ul>
<?php } ?>

app/code/Test/Categorytree/Block/Subcategory.php

<?php
namespace Test\Categorytree\Block;

use Magento\Framework\App\Filesystem\DirectoryList;

class Subcategory extends \Magento\Framework\View\Element\Template
{
    protected $categoryFactory;
    protected $layerResolver;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,  
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        array $data = []
    ) {
        $this->categoryFactory = $categoryFactory;   
        $this->_catalogLayer = $layerResolver->get();
        parent::__construct(
            $context,
            $data
        );
    }

    public function getCurrentCategoryInfo(){
        $categories = $this->_catalogLayer->getCurrentCategory()->getChildrenCategories();
        return $categories;
    }

    public function getCategoryData($id){
        return $category = $this->categoryFactory->create()->load($id);       
    }

    public function subCategory($id){
        $category = $this->getCategoryData($id);
        $childs = $category->getChildrenCategories();
        foreach($childs as $child){
            $subchild[] = $child->getData();
        }
        return $subchild;
    }
}

Define inside static block below code,

{{block class="Test\Categorytree\Block\Subcategory" template="Test_Categorytree::listing.phtml"}}</p>

call static block in your category from backend. Go to Category

Content Tab,

Content -> Add CMS Block set your cms block.

Display settings Tab: select Display mode value as static block only from dropdown.

Your Answer

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

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