Magento 2 create multiple fields in the system configuration programmatically

6
Multiple Fields on system configuration

Hello Friends,


This blog becomes very interesting because we will see How to create one configuration field which contains multiple fields and held data in the database.

Sometimes, to create a similar type of field we need to create multiple configuration field but using the below technique you just need to create only a single configuration field and using frontend model we will create subfields which held the data and when you try to save it then it will store in the core_config_data table with serialize format.

Let’s see some easy steps to create this kind of field.

Step 1: First, create system configuration field in the following location

app/code/[Namespace]/[Module]/etc/adminhtml/system.xml

<field id="multiplefields" translate="label" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0">
    <label>Multiple Fields</label>
    <frontend_model>[Namespace]\[Module]\Block\Adminhtml\Form\Field\MultipleFields</frontend_model>
    <backend_model>[Namespace]\[Module]\Config\Backend\MultipleFields</backend_model>
</field>

In the above code, we are used frontend_model & backend_model
frontend_model:  This block responsible for rendering the content of the columns in the table.
backend_model:  This used for saving and loading data from DB as a serialized format.

Step 2: Create the frontend model in the following location

app/code/[Namespace]/[Module]/Block/Adminhtml/Form/Field/MultipleFields.php

<?php

namespace [Namespace]\[Module]\Block\Adminhtml\Form\Field;
use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;

class MultipleFields extends AbstractFieldArray
{
    protected function _prepareToRender()
    {
        $this->addColumn('firstbox', ['label' => __('First Text Field'), 'class' => 'required-entry']);
        $this->addColumn('secondbox', ['label' => __('Second Text Field'), 'class' => 'required-entry']);        
        $this->_addAfter = false;
        $this->_addButtonLabel = __('Add New');
    }
}

In the above code, you can see that we have extends the \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray because we need table fields.

Here, we call _prepareToRender() function to declare out custom columns.

Step 3: Now, create the backend model in the following location

app/code/[Namespace]/[Module]/Config/Backend/MultipleFields.php

<?php
namespace [Namespace]\[Module]\Config\Backend;

use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Config\Value as ConfigValue;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;
use Magento\Framework\Serialize\SerializerInterface;

class MultipleFields extends ConfigValue
{
    /**
     * Json Serializer
     *
     * @var SerializerInterface
     */
    protected $serializer;
    /**
     * ShippingMethods constructor
     *
     * @param SerializerInterface $serializer
     * @param Context $context
     * @param Registry $registry
     * @param ScopeConfigInterface $config
     * @param TypeListInterface $cacheTypeList
     * @param AbstractResource|null $resource
     * @param AbstractDb|null $resourceCollection
     * @param array $data
     */
    public function __construct(
        SerializerInterface $serializer,
        Context $context,
        Registry $registry,
        ScopeConfigInterface $config,
        TypeListInterface $cacheTypeList,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->serializer = $serializer;
        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
    }
    /**
     * Prepare data before save
     *
     * @return void
     */
    public function beforeSave()
    {
        /** @var array $value */
        $value = $this->getValue();
        unset($value['__empty']);
        $encodedValue = $this->serializer->serialize($value);
        $this->setValue($encodedValue);
    }
    /**
     * Process data after load
     *
     * @return void
     */
    protected function _afterLoad()
    {
        /** @var string $value */
        $value = $this->getValue();
        if(isset($value)) {
            $decodedValue = $this->serializer->unserialize($value);
            $this->setValue($decodedValue);
        }
    }
}

In the above code, you need to create a backend model file that stores your data in core_config_table with serialize format.

Step 4: Get value from your field

We will create the function in Helper to get the value

<?php
namespace [Namespace]\[Module]\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Store\Model\ScopeInterface;
use Magento\Framework\Serialize\SerializerInterface;

class Data extends AbstractHelper
{
	protected $_scopeConfig;
	protected $serializer;

	public function __construct(
		Context $context,
	    SerializerInterface $serializer
	) {
		parent::__construct($context);
		$this->_scopeConfig = $context->getScopeConfig();		
		$this->serializer = $serializer;	    
	}

	public function getValueFromMultipleFields() {
		$data = $this->_scopeConfig->getValue('SECTION/GROUP/FIELD',ScopeInterface::SCOPE_STORE);
		$decodedValue = $this->serializer->unserialize($data);
		foreach($decodedValue as $value) {
			if($value['firstbox'] == 'Website 1') {
				return $value['secondbox'];
			}
		}
		return false;
	}	
}

Using the above code, now you just need to call your function from the helper to get the value that you want.

Thanks for reading this post!

About the author

I’m Magento Certified Developer having quite 5 years of commercial development expertise in Magento as well as in Shopify. I’ve worked primarily with the Magento and Shopify e-commerce platform, managing the complexities concerned in building e-commerce solutions tailored to a client’s specific desires.

Related Posts

Leave a Reply