How to Create a Magento 2 Admin Config & How Access to it using a Config Model

Henguelbert Loyo
8 min readFeb 1, 2023

--

Hi there! This is the first entry of a set of posts that I’ll be creating with the purpose of practice for Adobe Commerce Professional Developer Certification, and hope can help someone who’s starting with Magento 2 development.

Today we’ll learn how to create an admin configuration, some type of inputs we can create by default (Magento native configuration field types) and how to access to the values that the customer’s will put on them.

But before getting down to work, let me tell you the stack used to make this article:

  • Mac OS Ventura 13.1
  • PHP 8.1.6
  • Magento CE 2.4.5-p1
  • Docker Desktop 4.16.2

Note: I’m using the Mark Shust Magento-Docker environment, you can find it here.

  1. First step is create a system.xml file at this path app\code\[Vendor]\[Module]\etc\adminhtml\system.xml with the next initial content.
<?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>
</system>
</config>

Now we have to create the file, but first we need to identify where we want it, and for that is important to understand which are the parts of the admin configuration page, please see the image below.

Magento 2 Admin Configuration Page parts

The hierarchy three should look like this:

Configuration Page > Tab(s) > Section(s) > Group(s) > Field(s).

2. Keep this hierarchy on your mind, because is the base of the xml file structure we already created, so let’s type some code and see how we can structure our file starting for the node that will contain the rest of elements, the TAB node.

<?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="medium" translate="label" sortOrder="5">
<label>Medium</label>
</tab>
</system>
</config>

As you can see now we have the tab node, and it contains some attributes that I’m going to explain now:

  • id: this is the unique identifier for your tab, MUST be unique for each tab and have a descriptive name.
  • translate: this is useful when we need internationalize our labels, and indicate the node that should be translated in this case is the node “label”.
  • sortOrder: this attribute tells Magento the order of to show the Tab in the left bar.

3. After we created the Tab we need an specific section that store all our configurations so that’s the next step, let’s go for it!

<?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="medium" translate="label" sortOrder="5">
<label>Medium</label>
</tab>
<section id="social_media" sortOrder="20" translate="label" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Social Media</label>
<tab>medium</tab>
<resource>Magento_Backend::admin</resource>
</section>
</system>
</config>

In the code above we can observe that we have a Section node with attributes that we saw in the creation of Tab node, but now we have 3 new attributes and also 2 new nodes inside, lets start with nodes and after that I’ll talk about new attributes:

Nodes:

  • tab: this node contain the id of the tab that will be the parent node for the section we’re creating.
  • resource: this is the id of the ACL resource that our section will require to be accessed.

Attributes:

  • showInDefault: this attribute tells Magento if the section should be visible in the scope “Default”.
  • showInWebsite: this attribute tells Magento if the section should be visible in the scope “Website” or not.
  • showInStore: and finally this attribute tells if the section should be visible in the scope “Store” or not.

These attributes are boolean so must be 1 or 0.

At this point I know you should be thinking “wait, what’s a scope?”, let me explain a little bit this topic, I have to mention that this is a very important concept you should have in mind when are creating Admin Configurations for Magento 2, so please see the image below.

Magento 2 Admin Configuration Scopes

A Scope help us to keep specific values for configurations depending on what we want to achieve, we can have values that apply to the whole site (Default), values that only applies to a specific Country or Market (Website) or if only applies to a specific store or language (Store), so for example if we create a config to save the URL of and endpoint, this URL can be different for each country that we have in our store, or even different for each language in a country like Canada (English & French).

4. After that quick break let’s continue with the next step, the Group node:

<?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="medium" translate="label" sortOrder="5">
<label>Medium</label>
</tab>
<section id="social_media" sortOrder="20" translate="label" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Social Media</label>
<tab>medium</tab>
<resource>Magento_Backend::admin</resource>
<group id="facebook" sortOrder="10" translate="label" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Facebook</label>
</group>
</section>
</system>
</config>

5. If you can notice, group node have the same attributes than the section one so nothing new here and we can pass to the fields.

<?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="medium" translate="label" sortOrder="5">
<label>Medium</label>
</tab>
<section id="social_media" sortOrder="20" translate="label" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Social Media</label>
<tab>medium</tab>
<resource>Magento_Backend::admin</resource>
<group id="facebook" sortOrder="10" translate="label" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Facebook</label>
<field id="enabled" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="url" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Profile URL</label>
<comment>Please enter the URL of your Facebook Page profile</comment>
<depends>
<field id="enabled">1</field>
</depends>
</field>
</group>
</section>
</system>
</config>

Well now fields insert more nodes and one new attribute, so let’s do it in the same way we did it in step 3, start with nodes and then pass to attributes:

Nodes:

  • comment: this node allows us to show some help to the user, you can show what type of values can be entered or how you need to format data, etc.

depends: this allow us to control if a field is visible depending on the value of another field, we need to specify the id of the field and the value that make the field visible (if the field is in the same group you should use only the id of the field, but if the field is out of the group you should use the full path for field section/group/field).

  • source_model: this specify a model that provide a list of values to use in our field, in our example is an array with the values Yes & No.

Attribute:

  • type: this attribute set the type of entry, could be text, select, textarea, etc. You can see more types available here.

After these steps we should be able to see something like these images:

Config Disable
Config Enable

6. Now we need the capability of access to the values that the admin users store in those fields, in order to do that you need to create a model in the next path app/code/[Vendor]/[Module]/Model/Config.php, in my case I’ll name it just Config, but is a good practice to use a more descriptive name, something like module name before Config.

<?php
declare(strict_types=1);

namespace Medium\AdminConfig\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

class Config
{
public const XML_PATH_SOCIAL_MEDIA_FACEBOOK_ENABLED = "social_media/facebook/enabled";
public const XML_PATH_SOCIAL_MEDIA_FACEBOOK_URL = "social_media/facebook/url";

public function __construct(protected ScopeConfigInterface $scopeConfig)
{}

/**
* @param $storeId
* @return bool
*/
public function isFacebookEnabled($storeId = null): bool
{
return $this->scopeConfig->isSetFlag(
self::XML_PATH_SOCIAL_MEDIA_FACEBOOK_ENABLED,
ScopeInterface::SCOPE_STORE,
$storeId
);
}

/**
* @param $storeId
* @return string
*/
public function getFacebookUrl($storeId = null): string
{
return $this->scopeConfig->getValue(
self::XML_PATH_SOCIAL_MEDIA_FACEBOOK_URL,
ScopeInterface::SCOPE_STORE,
$storeId
);
}
}

Let’s take some minutes to analyze the code in the model, we have a normal PHP class, but first thing you can notice is that there are 2 constants, these constants contains the path for each field that we need to get from database, the path follow this pattern [section_id]/[group_id]/[field_id] so this need to match with the ids we place in our system.xml.

After that we have the constructor and then we have two methods (one per config), bot are very similar but let see the differences.

In the next block of code you could see that we use the method isSetFlag() from the scopeConfig object, this methods allow us to check for a boolean field, in this case our Enabled field is a select with Yes/No values, so it’s a boolean, we need to pass the path of the field, the scope (Store in this case) and the ID of the store we want to verify (if storeId is not provided Magento will return the value for Default Scope).

public function isFacebookEnabled($storeId = null): bool
{
return $this->scopeConfig->isSetFlag(
self::XML_PATH_SOCIAL_MEDIA_FACEBOOK_ENABLED,
ScopeInterface::SCOPE_STORE,
$storeId
);
}

In this other code we can see something similar, the only difference is that now we use the method getValue() from scopeConfig object, this method receive the same number and type of parameters than isSetFlag, but this method can return any type of value (strings, integers, boolean, objects, etc.) this is more generic, the previous one is specific for booleans.

public function getFacebookUrl($storeId = null): string
{
return $this->scopeConfig->getValue(
self::XML_PATH_SOCIAL_MEDIA_FACEBOOK_URL,
ScopeInterface::SCOPE_STORE,
$storeId
);
}

Now you can use this model in your controllers, view models, blocks or even another models to get the values of this configurations.

Note: You can check the values of these configs in your database running the next query

select * from core_config_data where path = 'social_media/facebook/enabled';

7. The only things left is learn how to set default values for the new configs that we just created, and for that we need to create the config.xml file in this path app/code/[Vendor]/[Module]/etc.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<social_media>
<facebook>
<enabled>1</enabled>
<url>https://facebook.com</url>
</facebook>
</social_media>
</default>
</config>

The structure of the nodes for this file is similar to the structure that we used in paths for our PHP model but adding first the node for scope in this case the Default one (if we need to specify values for specific Websites and Stores we can do it using the code of the website or code of store instead of Default), and inside of each tag for fields we put the desired value.

Hope this help you to get a more clear concept about what are configs, what files are involved in their creation and how we can get their values, see you in a next installment of this saga!

References

I let you some links that was consulted during the elaboration of this article and can help you to go deep on this topic.

https://developer.adobe.com/commerce/php/tutorials/backend/create-access-control-list-rule/

--

--

Henguelbert Loyo

CS Engineer | PHP Dev | Magento 2 Dev | Adobe Commerce Dev | Music | Gadgets | Tech | Coffee | Geek