Creating our own module for Magento 2, sooner or later we’ll need configuration that is clickable from the level of an administrator panel. It’s not very hard to create a configuration section in the backend – there are many resources online on this very subject, so we won’t delve on it in this short series of articles. Instead, we’ll focus on three other interesting issues: Source Model, Backend Model and Frontend Model.

These are powerful tools that let us adjust a seemingly easy configuration page to our needs. We can transmit various data to be selected, perform an operation before or after saving it, or display non-standard fields – all of this while maintaining the whole functionality of saving configuration of course.

For the purpose of this series we’ll create a simple module that we’ll use for tests. This module enables us to save data in the backend and then use them in the module or display them on the frontend. Just remember to clear the cache when introducing changes.

So let’s create our module:

//file app/code/Magently/Tutorial/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Magently_Tutorial" setup_version="0.1.0">
    </module>
</config>
//file app/code/Magently/Tutorial/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Magently_Tutorial',
    __DIR__
);

Now, it’s time to add our configuration section, which can be found in the Backend -> Stores -> Configuration.

//file app/code/Magently/Tutorial/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>
        <tab id="magently_tutorial" 
            translate="label" 
            sortOrder="1000">
            <label>Magently Tutorial</label>
        </tab>
        <section id="magently_tutorial_test" 
            translate="label" 
            type="text" 
            sortOrder="1" 
            showInDefault="1" 
            showInWebsite="1" 
            showInStore="1">
            <label>Source models</label>
            <tab>magently_tutorial</tab>
            <resource>Magently_Tutorial::config</resource>
            <group id="test" 
            translate="label" 
            type="text" 
            sortOrder="1" 
            showInDefault="1" 
            showInWebsite="1" 
            showInStore="1">
                <label>Source model test</label>
                <field id="yesno_source_model" 
                    translate="label" 
                    type="select" 
                    sortOrder="1" 
                    showInDefault="1" 
                    showInWebsite="1" 
                    showInStore="1">
                    <label>Yes/no source model</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
            </group>
        </section>
    </system>
</config>

We’ve added one option group with one field.screenshot1

We’ll subsequently create new files and modify the above one by adding new groups to test the new functionalities.

Today, we’ll take a closer look at the Source Model.

Shortly speaking, the Source Model is a model of data that we can use for configuration. There are many source models created by Magento developers. For example, in our first field we used Magento\Config\Model\Config\Source\Yesno that enables us to choose Yes or No from the select. Other helpful models include the following:

  • Magento\Config\Model\Config\Source\Yesnocustom that apart from Yes/No gives another option: Specified;
  • Magento\Config\Model\Config\Source\Enabledisable that saves 0/1 values in the database;
  • Magento\AdminNotification\Model\Config\Source\Frequency that is used in notifications and enables us to select frequency (every 1, 2, 6, 12, 24 hours);
  • Magento\Catalog\Model\Config\Source\TimeFormat that enables us to set the time format (12 h/24 h);
  • Magento\Cron\Model\Config\Source\Frequency that enables us to choose from Daily/Weekly/Monthly (in the database it’s saved as D/W/M respectively);
  • Magento\GoogleAdwords\Model\Config\Source\Language that enables saving a 2-letter code of a given language in the ISO 639-1 format (e.g. en);
  • Magento\Config\Model\Config\Source\Locale that acts similarly to the above one, but it pertains a locale code (e.g. en_US).

However, what if we want to have distinctive values? We can create our own Source Model. So let’s do it – let’s add a new field to our group:

//file app/code/Magently/Tutorial/etc/adminhtml/system.xml

...
                <field id="custom_select" 
                    translate="label" 
                    type="select" 
                    sortOrder="2" 
                    showInDefault="1" 
                    showInWebsite="1" 
                    showInStore="1">
                    <label>Custom source model</label>
                    <source_model>Magently\Tutorial\Model\Config\Source\Custom</source_model>
                </field>
...

And create a new source model:

//file app/code/Magently/Tutorial/Model/Config/Source/Custom.php

<?php

namespace Magently\Tutorial\Model\Config\Source;

class Custom implements \Magento\Framework\Option\ArrayInterface
{ 
    /**
     * Return array of options as value-label pairs, eg. value => label
     *
     * @return array
     */
    public function toOptionArray()
    {
        return [
            'value' => 'Label',
            'another_value' => 'Another value',
        ];
    }
}

screenshot2

As you can see, our custom source model – as well as every other one – implements the interface \Magento\Framework\Option\ArrayInterface. This way we can be sure that every source model has the toOptionArray() method that returns arrays with available options.

In the next article we’ll deal with the Backend Model that enables us, among other things, to control actions before or after saving the configuration, so stay tuned!