This article is about Magento 2 multi-select in system configuration . Getting all available categories and display them in a system config multi-select field list can be tricky sometimes. In this tutorial i will try to explain it swiftly and in a simple way that how can you do it in magento 2. There can be various ways of doing it.We will discuss one or two efficient ways of doing so here.
Let’s start our tutorial, here we will discuss different ways of doing it. I hope you are familiar with magento 2 and if yes, you will be able to move along nicely.
First of all modify
QaisarSatti/HelloWorld/etc/adminhtml/system.xml
and paste the following code
<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>QaisarSatti_HelloWorld::config</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>QaisarSatti\HelloWorld\Model\Config\Source\Categorylist</source_model>
</field>
</group>
</section>
</system>
</config>
Now
QaisarSatti/HelloWorld/etc/acl.xml
add Acl
<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="QaisarSatti_HelloWorld::config" title="Module Section" />
</resource>
</resource>
</resource>
</resource>
</resources>
</acl>
</config>
Now add
QaisarSatti/HelloWorld/Model/Config/Source/Categorylist.php
namespace QaisarSatti\HelloWorld\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;
}
}
Furthermore, let’s discuss another way of doing so. Here In system.xml file field for multi select of category is like:
<label>Setting</label>
<field id="cateogry" translate="label" type="multiselect" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Select Category</label>
<source_model>QaisarSatti\HelloWorld\Model\Config\Source\Categorylist</source_model>
</field>
</group>
Now create a file Categorylist.php in QaisarSatti\HelloWorld\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;
}
}
But in this case you’ll get first level only and categories included in menu.
That’s it from this tutorial. I strongly believe there is always room for improvement.So i am open for any suggestion and feed back. Please feel free to leave hat you are thinking in the comments section below. Cheers.