Building Magento 2 Extension – ExtendedConfig

As I promised, it is continuation for ExtendedConfig module. I will show how to add module configuration settings into Stores->Configuration page, with minimal amount of “coding” 🙂

Understanding Store Configuration

First step for every customization is to investigate functionality, which is going to be customized. Check how it works natively. So let’s open Stores->Configuration page and investigate it.

ExtendedConfig-configpage

On left side of the page there is navigation menu with tabs and sections. Tabs are not clickable, as they are just used for grouping sections. Sections are clickable and consist of groups. Every group consists of form fields. If navigate through different sections on the page, what user always see – is a form.

On screenshot – GENERAL (all capitals) is tab, General is section and Store Information is one group in the section, with several form fields. For navigation by the form we need to use Section->Group->Field path, later we will see example.

The Configuration page is rendered by Magento_Config module. It uses information from <system><config> node of XML configuration, the content for node is located in adminhtml/system.xml for each module. If module needs to add configuration into the page, it must have adminhtml/system.xml file with correct content.

So i am going to create the file app/code/Maxyek/ExtendedConfig/etc/adminhtml/system.xml with this content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
    <system>
        <tab id="maxyek" sortOrder="1">
            <label>Maxyek</label>
        </tab>
        <section id="maxyek_general"  showInDefault="1">
            <tab>maxyek</tab>
            <label>General</label>
            <resource>Magento_Config::config</resource>
            <group id="personal"  showInDefault="1">
                <label>Personal Settings</label>
                <field id="name" type="text" showInDefault="1">
                    <label>Owner name</label>
                </field>
            </group>
        </section>
    </system>
</config>

In order to apply the changes Magento cache must be refreshed. Easy way to do it, is common for Magento 1 and Magento 2 -go to System->Cache Management and make manual refresh all caches. After cache refreshed additional tab and section will appear on Stores->Configuration page, as illustrated here:

ExtendedConfig-configpage2

Just by adding 1 XML file with 19 lines of content, I have created new and completely functional configuration tab, section and form field  Easy, right?!

<system><config>What is this?</system></config>

If you know how to build  XML for system config, you will be able easily create complex config settings for your module, just with small amount of development. Let’s go through the XML content.

<system><config>

As mentioned before, Magento_Config module will read information from <system><config> node of store configuration. Thats why the XML starts from the nodes.

Out of box Magento 2 provides validation for configuration and layouts using XSD. It is very helpful tool for developers, which saves a tons of time on building XML content. Magento_Config provides XSD for validating system config structure. I am using PHPStorm, and editor allows me to see if my content correct, after i specified location schema in root element <config>:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
    <system>

<tab>

<tab> is creating new tab in navigation menu with label defined in <label>, and order specified in sortOrder attribute. Each tab must have unique id:

<tab id="maxyek" sortOrder="1">
     <label>Maxyek</label>
</tab>

Tab will not be rendered if there is no section with group and at least one field. Tab has only one sub-node <label> and 5 attributes:

Attribute Obligatoriness Description
id mandatory Used to identify tab
translate optional Used to specify sub-nodes for translation (only label)
module optional Used to specify translation module
class optional Used to specify css class
sortOrder optional Used to specify the order of tab

<section>

Section adds clickable item in left navigation menu, with text declared in <label> node. Section will not be rendered if there is no group and field declared within it. Section has <tab> node, it defines tab the section will be linked.  Store, WebSite and Default Store visibility may be declared as attribute. In the example the section will be rendered in Store View = Default Config.

<section id="maxyek_general"  showInDefault="1">
    <tab>maxyek</tab>
    <label>General</label>
    <resource>Magento_Config::config</resource>

Section attribute ‘id‘ must be unique in scope of section’s identifiers.

Attribute Obligatoriness Description
id mandatory Used to identify section
translate optional Used to specify sub-nodes for translation
module optional Used to specify translation module
sortOrder optional Used to specify the order of sections
type optional Used to specify the rendered element
showInDefault optional Used to specify the presenting in default scope
showInStore optional Used to specify the presenting in store scope
showInWebsite optional Used to specify the presenting in website scope

Even if resource is optional sub-node, ACL needs to be specified, to allow rendering. Taking in account the module depends on Magento_Config, i used Magento_Config::config ACL resource.

Sub-nodes for section node:

sub-node Obligatoriness Description
label mandatory Used to specify the section title
class optional Used to defined css class
resource optional Used to defined acl resource
header_css optional Used to defined css class for header
tab mandatory Used to defined in which tab section will be rendered

<group>

Group combines several form fields under foldable ui group, with title in <label> node. Group won’t be rendered if there is no active field defined within it, except if there is renderer class specified, in this case group will be end-point element. Similar to section, group has optional visibility attributes. In ExtendedConfig it is visible on default config. Group attribute ‘id‘ must be unique per section.

<group id="personal"  showInDefault="1">
    <label>Personal Settings</label>

Possible list of attributes:

Attribute Obligatoriness Description
id mandatory Used to identify group
translate optional Used to specify sub-nodes for translation
module optional Used to specify translation module
sortOrder optional Used to specify the order of group
type optional Used to specify the rendered element
showInDefault optional Used to specify the presenting in default scope
showInStore optional Used to specify the presenting in store scope
showInWebsite optional Used to specify the presenting in website scope

Defined list of sub-nodes:

sub-node Obligatoriness Description
label mandatory Used to specify the section title
frontend_model optional Used to specify the frontend rendered model
clone_fields optional Used to define fields can be cloned
clone_model optional Used to specify the model for cloning fields
fieldset_css optional Used to defined css class
expanded optional Used to specify group must be expanded after rendering

<field>

Filed is form field element, with mandatory defined input type, id and label attributes.

<field id="name" type="text" showInDefault="1">
    <label>Owner name</label>
</field>

type=”text” – define the field as text input, it stores information about owner name.

Magento 2 has solid list of pre-defined types of fields, and it is easy to create own one, by extending the class:

Magento\Framework\Data\Form\Element\AbstractElement

List of existing elements can be found in the namespace:

Magento\Framework\Data\Form\Element\

ExtendedConfig-elements

In this post I will not dive into field element details, it deserves separate post, because it allows to play with different renderers, data sources and backend models.  If you interested into details – just add comment to the post with exact question.

->getValue($configPath)

Configuration makes sense if it can be provided by request. So next step is – get access to the saved configuration value. There is interface in Magento 2 which allow to access scope config data:

\Magento\Framework\App\Config\ScopeConfigInterface

Magento Dependency Injection framework will provide correct instance of config, if I will declare the interface in constructor of my Config class. The instance of the Config class needs to know path, where config data is stored. Pattern for data is [section_id]/[group_id]/[field_id], in ExtendedConfig module it is “maxyek_general/personal/name”. Below code which allow to read the information from everywhere in codebase:

class Config extends Object
{
    /**
     * Core store config
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $_scopeConfig;
   
   /* 
    * @var \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    */
    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ){
        $this->_scopeConfig = $scopeConfig;
    }

   /* 
    * Get owner name
    * @return string
    */
    public function getOwnerName()
    {
        $name = $this->_scopeConfig->getValue(
            'maxyek_general/personal/name'
        );
        return $status;
    }
}

Thoughts

Magento 2 provides very flexible and intuitive way for customization and extending System Configuration. Ability to create “standard” logic without even adding php code, allows developers to focus on pure business logic code, and as result saves a ton of time, and money for merchants.

In this post i didn’t cover field dependencies, block overrides, field frontend, backend and source models, which make configuration XML very power tool. I don’t want to create “specification” or “manuals”, but rather to show by example how Magento 2 helps achieve goals faster. On different events, i heart from some community members their fears if Magento 2 will be even more complex then Magento 1. I hope this case will help to kill at least 1 fear.

Advertisements

8 thoughts on “Building Magento 2 Extension – ExtendedConfig

  1. Hi!

    Thanks for your explanation, but how can I SET a configuration value? I am developing a kind of automated setup where I want to set several store config values by code.

    I tried the following:

    $this->_config = $this->_objectManager->get(‘\Magento\Framework\App\Config\MutableScopeConfigInterface
    $this->_config->setValue($path,$value);

    But it seems the values are not saved?

    Like

      1. Just load \Magento\Config\Model\ResourceModel\Config and then use
        $this->configResourceModel->saveConfig($configPath, $value, ‘default’, 0);

        Like

  2. Great post!
    I am looking for a way to embed an iframe inside a group in Admin Panel. I added a section (group) for general configurations and now I want to add another section in order to include an iframe from my website dashboard. Any clue to do this?

    Thanks

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s