How to add custom "table-like" configuration field in Magento admin

March 23, 2017 in #Magento

In this post I'll show you an example of adding custom "table-like" system configuration field in Magento admin. And by "table-like" I mean something like this:

Magento Custom System Configuration Field


If you are looking for an example of adding standard system configuration fields in Magento admin (text field, select, etc.), you may still benefit from this post as the procedure is 95% same.


Magento refers to this type of configuration field as "array field", and (in Magento CE 1.9.2.4) there are only two fields of this type - "Minimum Qty Allowed in Shopping Cart" field under the "Inventory" section and theme exceptions under the "Design" section. Quite specific type, yet, sometimes very useful.

The value of such admin configuration field will be saved as serialized array in the database, and you are responsible for un-serializing it upon retrieval (except for the admin configuration section since Magento will partially take care of that for you). The example of config retrieval is included in the code below. Now let's build that module!


Note - this example will use the namespace "ArchApps" and module name "CustomAdminConfig" - consider replacing them with names that are appropriate for you.


1) Register new module - create ArchApps_CustomAdminConfig.xml file in app/etc/modules/ directory with following content:

<?xml version="1.0"?>  
<config>  
    <modules>
        <ArchApps_CustomAdminConfig>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Adminhtml />
            </depends>
        </ArchApps_CustomAdminConfig>
    </modules>
</config>  

2) Configure the module - create config.xml file in app/code/local/ArchApps/CustomAdminConfig/etc/ directory with following content:

<?xml version="1.0"?>  
<config>  
    <modules>
        <ArchApps_CustomAdminConfig>
            <version>0.1.0</version>
        </ArchApps_CustomAdminConfig>
    </modules>

    <global>
        <!-- Module will use blocks -->
        <blocks>
            <archapps_customadminconfig>
                <class>ArchApps_CustomAdminConfig_Block</class>
            </archapps_customadminconfig>
        </blocks>

        <!-- Module will use helpers -->
        <helpers>
            <archapps_customadminconfig>
                <class>ArchApps_CustomAdminConfig_Helper</class>
            </archapps_customadminconfig>
        </helpers>
    </global>
</config>  

3) Add configuration field - add system.xml file in app/code/local/ArchApps/CustomAdminConfig/etc/ directory with following content:

<?xml version="1.0"?>  
<config>  
    <sections>
        <!-- Adding New Group Under System -> Configuration -> General -> General -->
        <general>
            <groups>
                <archapps_customadminconfig translate="label" module="archapps_customadminconfig">
                    <label>Custom Admin Config</label>
                    <sort_order>200</sort_order>
                    <show_in_store>1</show_in_store>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <frontend_type>text</frontend_type>
                    <fields>
                        <!-- Adding new custom, "table-like" configuration field -->
                        <cutom_field_one translate="label">
                            <label>Custom Config Field One</label>
                            <sort_order>10</sort_order>
                            <show_in_store>1</show_in_store>
                            <show_in_website>1</show_in_website>
                            <show_in_default>1</show_in_default>
                            <!-- Specific backend class to handle serialized data -->
                            <backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
                            <!-- Specific frontend class to render custom field -->
                            <frontend_model>archapps_customadminconfig/adminhtml_customFieldOne</frontend_model>
                        </cutom_field_one>
                    </fields>
                </archapps_customadminconfig>
            </groups>
        </general>
    </sections>
</config>  

The important bits here are the backend_model and frontend_model nodes. The backend_model node defines how the data will be prepared before saved / after loaded to / from the database. The frontend_model, on the other hand, specifies how the field will be presented to user in Magento admin configuration section.

We're using the adminhtml/system_config_backend_serialized_array class as backend_model and our module's archapps_customadminconfig/adminhtml_customFieldOne class as frontend_model (which we are about to create).

The adminhtml/system_config_backend_serialized_array is a default part of Magento's code-base and refers to Mage_Adminhtml_Model_System_Config_Backend_Serialized_Array class.

5) Create block class - create CustomFieldOne.php file in app/code/local/ArchApps/CustomAdminConfig/Block/Adminhtml/ directory with following content:

<?php

class ArchApps_CustomAdminConfig_Block_Adminhtml_CustomFieldOne  
    extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
{
    /**
     * Add custom config field columns, set template, add values.
     */
    public function __construct()
    {
        /** @var ArchApps_CustomAdminConfig_Helper_Data $helper */
        $helper = Mage::helper('archapps_customadminconfig');

        $this->addColumn('column_one', array(
            'style' => 'width:200px',
            'label' => $helper->__('Column One'),
        ));

        $this->addColumn('column_two', array(
            'style' => 'width:200px',
            'label' => $helper->__('Column Two'),
        ));

        $this->addColumn('column_three', array(
            'style' => 'width:80px',
            'label' => $helper->__('Column Three'),
        ));

        parent::__construct();
    }
}

This here is the class that will be used to render the custom config field and this is where we specify the columns that the field will have. Add as many columns as you wish via addColumn method and style them according to your needs.

Look into Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract class's addColumn method for more details about what attributes / options can be added to each column.

6) Create helper class - create Data.php file in app/code/local/ArchApps/CustomAdminConfig/Helper/ directory with following content:

<?php

class ArchApps_CustomAdminConfig_Helper_Data extends Mage_Core_Helper_Abstract  
{
    const XML_PATH_CONFIG_FIELD_ONE = 'general/archapps_customadminconfig/cutom_field_one';

    /**
     * Returns un-serialized data of the custom config field one
     *
     * @return array
     */
    public function getConfigFieldOne()
    {
        $config = Mage::getStoreConfig(self::XML_PATH_CONFIG_FIELD_ONE);

        if (!$config) {
            return array();
        }

        try {
            $config = Mage::helper('core/unserializeArray')->unserialize($config);
        } catch (Exception $exception) {
            Mage::logException($exception);
            $config = array(); // Return an array if failed to un-serialize data
        }

        return $config;
    }
}

Noteworthy part here is the un-serialization of the data we retrieve from the database. We are using the standard config retrieval method first:

$config = Mage::getStoreConfig(self::XML_PATH_CONFIG_FIELD_ONE);

And then un-serialize the retrieved data via Magento's utility method:

$config = Mage::helper('core/unserializeArray')->unserialize($config);

Which then returns a nicely formatted array. In case if there is no such config value, empty array will be returned. In case if an exception is thrown in unserialize method, log the exception message and return empty array. Just keeping things consistent!


Now that this is all done, the new field should appear in the Magento admin and you should be able to add and remove field's rows and successfully save it! To retrieve the data of this config field use:

$config = Mage::helper('archapps_customadminconfig')->getConfigFieldOne();
var_dump($config);

---

array (size=3)  
  '_1507049027926_926' => 
    array (size=3)
      'column_one' => string 'First Column One' (length=16)
      'column_two' => string 'First Column Two' (length=16)
      'column_three' => string 'First 3' (length=7)
  '_1507049044066_66' => 
    array (size=3)
      'column_one' => string 'Second Column One' (length=17)
      'column_two' => string 'Second Column Two' (length=17)
      'column_three' => string 'Second 3' (length=8)
  '_1507049057387_387' => 
    array (size=3)
      'column_one' => string 'Third Column One' (length=16)
      'column_two' => string 'Third Column Two' (length=16)
      'column_three' => string 'Third 3' (length=7)

You can easily iterate the config rows and access each field value using the column names you used in addColumn method (first argument):

$config = Mage::helper('archapps_customadminconfig')->getConfigFieldOne();

foreach ($config as $row) {  
    var_dump($row['column_one']);
    var_dump($row['column_two']);
    var_dump($row['column_three']);
}

And that is it, you should now have a tiny, but working Magento module that adds custom admin configuration field! Cheers!