5

My problem to get all available categories and display them in a system config multi-select field list.

Here is a link for Magento 1.x. How can it be achieved for Magento 2.x?

4 Answers 4

21

VendorName/ModuleName/etc/adminhtml/system.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="module_section" translate="label" type="text"
                 sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Module</label>
            <tab>tab_name</tab>
            <resource>VendorName_ModuleName::config_module_name</resource>
            <group id="module_section_page" translate="label" type="text"
                   sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Module page settings</label>
                <field id="latest_category" translate="label" type="multiselect" sortOrder="12" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>New Product Category</label>
                    <source_model>VendorName\ModuleName\Model\Config\Source\Categorylist</source_model>
                </field>
            </group>
        </section>
    </system>
</config>

VendorName/ModuleName/etc/acl.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/acl.xsd">
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="VendorName_ModuleName::config_module_name" title="Module Section" />
                        </resource>
                    </resource>
                </resource>
            </resource>
        </resources>
    </acl>
</config>

VendorName/ModuleName/Model/Config/Source/Categorylist.php

<?php

namespace VendorName\ModuleName\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Categorylist implements ArrayInterface
{
    protected $_categoryFactory;
    protected $_categoryCollectionFactory;

    public function __construct(
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory
    )
    {
        $this->_categoryFactory = $categoryFactory;
        $this->_categoryCollectionFactory = $categoryCollectionFactory;
    }

    public function getCategoryCollection($isActive = true, $level = false, $sortBy = false, $pageSize = false)
    {
        $collection = $this->_categoryCollectionFactory->create();
        $collection->addAttributeToSelect('*');

        // select only active categories
        if ($isActive) {
            $collection->addIsActiveFilter();
        }

        // select categories of certain level
        if ($level) {
            $collection->addLevelFilter($level);
        }

        // sort categories by some value
        if ($sortBy) {
            $collection->addOrderField($sortBy);
        }

        // select certain number of categories
        if ($pageSize) {
            $collection->setPageSize($pageSize);
        }

        return $collection;
    }

    public function toOptionArray()
    {
        $arr = $this->_toArray();
        $ret = [];

        foreach ($arr as $key => $value)
        {
            $ret[] = [
                'value' => $key,
                'label' => $value
            ];
        }

        return $ret;
    }

    private function _toArray()
    {
        $categories = $this->getCategoryCollection(true, false, false, false);

        $catagoryList = array();
        foreach ($categories as $category)
        {
            $catagoryList[$category->getEntityId()] = __($this->_getParentName($category->getPath()) . $category->getName());
        }

        return $catagoryList;
    }

    private function _getParentName($path = '')
    {
        $parentName = '';
        $rootCats = array(1,2);

        $catTree = explode("/", $path);
        // Deleting category itself
        array_pop($catTree);

        if($catTree && (count($catTree) > count($rootCats)))
        {
            foreach ($catTree as $catId)
            {
                if(!in_array($catId, $rootCats))
                {
                    $category = $this->_categoryFactory->create()->load($catId);
                    $categoryName = $category->getName();
                    $parentName .= $categoryName . ' -> ';
                }
            }
        }

        return $parentName;
    }
}

Here is a screenshot: enter image description here

2
  • Sir can you please explain... I used the same class as you mentioned above and its works perfectly for me.. but when I submit my module to Magento QA they send my module back to me with a note that dublicating the class Category.php since I used Category.php in place of Categorylist.php
    – Asad Khan
    Commented Apr 29, 2019 at 8:48
  • i was not looking for this particularly but this helps me in my issue. 1+ upvoted
    – Asad Ullah
    Commented Mar 19, 2021 at 13:07
8

In system.xml file field for multi select of category is like:

<group id="bannerblock_setting" translate="label" type="text" default="1" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Setting</label>
    <field id="bannerlist" translate="label" type="multiselect" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
        <label>Select Category</label>
        <!-- <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>-->
        <source_model>Ipragmatech\Bannerblock\Model\Config\Source\Categorylist</source_model>
    </field>
</group>

Create a file Categorylist.php in Companyname\Modulename\Model\Config\Source

namespace Companyname\Modulename\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Categorylist implements ArrayInterface
{
    protected $_categoryHelper;

    public function __construct(\Magento\Catalog\Helper\Category $catalogCategory)
    {
        $this->_categoryHelper = $catalogCategory;
    }

    /*
     * Return categories helper
     */

    public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
    {
        return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
    }

    /*  
     * Option getter
     * @return array
     */
    public function toOptionArray()
    {


        $arr = $this->toArray();
        $ret = [];

        foreach ($arr as $key => $value)
        {

            $ret[] = [
                'value' => $key,
                'label' => $value
            ];
        }

        return $ret;
    }

    /*
     * Get options in "key-value" format
     * @return array
     */
    public function toArray()
    {

        $categories = $this->getStoreCategories(true,false,true);

        $catagoryList = array();
        foreach ($categories as $category){

            $catagoryList[$category->getEntityId()] = __($category->getName());
        }

        return $catagoryList;
    }

}

Here is a screenshot:

enter image description here


3
  • But in this case you'll get first level only and categories included in menu
    – WaPoNe
    Commented Dec 12, 2016 at 13:46
  • You can little part modify code and get call subcategories..it upon you to make category and subcategory array and return that.
    – Manish
    Commented Dec 13, 2016 at 4:41
  • Hi @manish I have followed your post/answer everything working fine but we are facing an issue with displaying selected value after saving at admin end attribute level can you please suggest is there any thing i missed it. Commented Oct 31, 2018 at 9:07
0

If somebody needs more clear code, you are welcome :)

<?php

declare(strict_types=1);

namespace Vendor\Module\Model\Config\Source;

use Magento\Catalog\Helper\Category as CategoryHelper;
use Magento\Framework\Option\ArrayInterface;

class Category implements ArrayInterface
{
    /**
     * @var \Magento\Catalog\Helper\Category
     */
    protected $categoryHelper;

    /**
     * Category constructor.
     *
     * @param \Magento\Catalog\Helper\Category $catalogCategory
     */
    public function __construct(CategoryHelper $catalogCategory)
    {
        $this->categoryHelper = $catalogCategory;
    }

    /**
     * @inheritDoc
     */
    public function toOptionArray(): array
    {
        $options = [];

        foreach ($this->toArray() as $key => $value) {
            $options[] = ['value' => $key, 'label' => $value,];
        }

        return $options;
    }

    /**
     * @return array
     */
    public function toArray(): array
    {
        $categoryList = [];

        foreach ($this->categoryHelper->getStoreCategories() as $category) {
            $categoryList[$category->getEntityId()] = $category->getName();
        }

        return $categoryList;
    }
}
0

If any one want code with parent and child category then follow below code :

<?php

namespace Vendor\Module\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Category implements ArrayInterface
{
    protected $_categoryFactory;
    protected $_categoryCollectionFactory;
    protected $_storeManager;

    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ) {
        $this->_categoryCollectionFactory = $categoryCollectionFactory;
        $this->_categoryFactory = $categoryFactory;
         $this->_storeManager = $storeManager;
    }

    /**
    * Get category collection
    *
    * @param bool $isActive
    * @param bool|int $level
    * @param bool|string $sortBy
    * @param bool|int $pageSize
    * @return \Magento\Catalog\Model\ResourceModel\Category\Collection or array
    */
    public function getCategoryCollection($isActive = true, $level = false, $sortBy = false, $pageSize = false)
    {
        $collection = $this->_categoryCollectionFactory->create();
        $collection->addAttributeToSelect('*');
        $collection->setStore($this->_storeManager->getStore());


        // select only active categories
        if ($isActive) {
            $collection->addIsActiveFilter();
        }

        // select categories of certain level
        if ($level) {
            $collection->addLevelFilter($level);
        }

        // sort categories by some value
        if ($sortBy) {
            $collection->addOrderField($sortBy);
        }

        // select certain number of categories
        if ($pageSize) {
            $collection->setPageSize($pageSize);
        }

        return $collection;
    }

    public function toOptionArray()
    {
        $arr = $this->_toArray();
        $ret = [];
        foreach ($arr as $key => $value){
            $ret[] = [
                'value' => $key,
                'label' => $value
            ];
        }    
        return $ret;
    }

    private function _toArray()
    {
        $categories = $this->getCategoryCollection(true, false, false, false);
        $catagoryList = array();
        foreach ($categories as $category){
           $catagoryList[$category->getEntityId()] = __($this->_getParentName($category->getPath()) . $category->getName());
        }
        return $catagoryList;
    }

    private function _getParentName($path = '')
    {
        $parentName = '';
        $rootCats = array(1,2);  
        $catTree = explode("/", $path);
        array_pop($catTree);     
        if($catTree && (count($catTree) > count($rootCats))){
            foreach ($catTree as $catId){
                if(!in_array($catId, $rootCats)){
                    $category = $this->_categoryFactory->create()->load($catId);
                    $categoryName = $category->getName();
                    $parentName .= $categoryName . ' -> ';
                }
            }
        }
        return $parentName;
    }
}

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.