system.xml Configuration
Complete 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>
<section id="vendor_prep" type="text" sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Vendor Prep</label>
<tab>general</tab>
<group id="general" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>General Settings</label>
<field id="enabled" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Enable Module</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="title" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Module Title</label>
<validate>required-entry</validate>
</field>
</group>
<group id="api" type="text" sortOrder="20" showInDefault="1" showInWebsite="0" showInStore="0">
<label>API Settings</label>
<field id="api_url" type="text" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0">
<label>API URL</label>
<validate>required-entry validate-url</validate>
</field>
<field id="api_key" type="obscure" sortOrder="20" showInDefault="1" showInWebsite="0" showInStore="0">
<label>API Key</label>
<backend_model>Magento\Config\Model\Config\Backend\Obfuscate</backend_model>
</field>
</group>
</section>
</system>
</config>
Field Types
| Type | Purpose |
|---|---|
| text | Text input |
| textarea | Multi-line text |
| select | Dropdown |
| multiselect | Multiple dropdown |
| yesno | Yes/No (special select) |
| price | Price input |
| image | Image upload |
| obscure | Masked input (password-like) |
Admin Menu
menu.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
<!-- Add to existing menu -->
<add id="Amazon_Prep::prep"
title="Prep Manager"
module="Amazon_Prep"
sortOrder="200
resource="Amazon_Prep::prep"/>
<!-- Add child items -->
<add id="Amazon_Prep::prep_warranties"
title="Warranties"
module="Amazon_Prep"
sortOrder="10"
parent="Amazon_Prep::prep"
resource="Amazon_Prep::warranties"/>
<add id="Amazon_Prep::prep_settings"
title="Settings"
module="Amazon_Prep"
sortOrder="20"
parent="Magento_Backend::stores"
action="adminhtml/system_config/edit/section/vendor_prep"
resource="Amazon_Prep::settings"/>
</menu>
</config>
Menu Item Attributes
| Attribute | Description |
|---|---|
| id | Unique identifier (Vendor_Module::item) |
| title | Display text |
| module | Module that owns this item |
| sortOrder | Display order |
| parent | Parent menu item ID |
| action | URL to navigate to |
| resource | ACL resource for permissions |
Adding to Existing Menu
<!-- Add under Sales menu -->
<add id="Amazon_Prep::warranties"
title="Warranties"
module="Amazon_Prep"
sortOrder="100"
parent="Magento_Sales::sales Operations"
resource="Amazon_Prep::warranties"/>
Source Models and Backend Models
Custom Source Model
<?php
namespace Amazon\Prep\Model\Config\Source;
class WarrantyType implements \Magento\Framework\Option\ArrayInterface
{
public function toOptionArray(): array
{
return [
['value' => 'standard', 'label' => __('Standard')],
['value' => 'extended', 'label' => __('Extended')],
['value' => 'premium', 'label' => __('Premium')],
];
}
}
Use in system.xml:
<field id="warranty_type" type="select" sortOrder="10" showInDefault="1">
<label>Warranty Type</label>
<source_model>Amazon\Prep\Model\Config\Source\WarrantyType</source_model>
</field>
Backend Model
<?php
namespace Amazon\Prep\Model\Config\Backend;
class WarrantyDuration extends \Magento\Config\Model\Config\Backend\AbstractBackend
{
public function afterSave(): void
{
$value = $this->getValue();
if ($value < 1 || $value > 120) {
throw new \Magento\Framework\Exception\LocalizedException(
__('Duration must be between 1 and 120 months')
);
}
}
public function afterLoad(): void
{
// Process value after loading from database
}
}
Use in system.xml:
<field id="warranty_duration" type="text" sortOrder="20" showInDefault="1">
<label>Duration (months)</label>
<validate>validate-digits validate-range range-1-120</validate>
<backend_model>Amazon\Prep\Model\Config\Backend\WarrantyDuration</backend_model>
</field>
Backend Model Methods
| Method | When Called |
|---|---|
| beforeSave() | Before value is saved |
| afterSave() | After value is saved |
| beforeLoad() | Before value is loaded |
| afterLoad() | After value is loaded |
| _construct() | During initialization |
Accessing Configuration Values
ScopeConfigInterface
<?php
namespace Amazon\Prep\Service;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
class ConfigService
{
public function __construct(
private ScopeConfigInterface $scopeConfig
) {}
public function isEnabled(): bool
{
return (bool)$this->scopeConfig->getValue(
'vendor_prep/general/enabled',
ScopeInterface::SCOPE_STORE
);
}
public function getTitle(): string
{
return $this->scopeConfig->getValue(
'vendor_prep/general/title',
ScopeInterface::SCOPE_STORE
) ?? 'Default Title';
}
public function getApiUrl(): string
{
return $this->scopeConfig->getValue(
'vendor_prep/api/api_url',
ScopeInterface::SCOPE_STORE
);
}
}
Configuration Path Format
section/group/field
Example: vendor_prep/general/enabled
^^^^^^^ ^^^^^^^^ ^^^^^^^
section group field
Access in Block/Template
// In block class
public function isEnabled(): bool
{
return (bool)$this->_scopeConfig->getValue(
'vendor_prep/general/enited'
);
}
// In template
$isEnabled = $block->isEnabled();
Access in Layout XML
<block class="..." name="...">
<arguments>
<argument name="enabled" xsi:type="object">
Magento\Framework\App\Config\ScopeConfigInterface
</argument>
</arguments>
</block>
XMLPath to Scope Config
// Get all config values for a section
$sectionConfig = $this->scopeConfig->getValue('vendor_prep');
// Get nested value
$apiUrl = $sectionConfig['api']['api_url'];
// With default value
$value = $this->scopeConfig->getValue(
'vendor_prep/general/title',
ScopeInterface::SCOPE_STORE,
$storeId
) ?? 'Default';
Quiz
1. What file defines admin menu items?
2. What does a backend model do?
3. How do you access a config value in PHP?
Flashcards
Question
What does system.xml define?
Click to reveal answer
Answer
Admin configuration sections, groups, and fields
Question
What is the config path format?
Click to reveal answer
Answer
section/group/field (e.g., vendor_prep/general/enabled)
Question
What does a source model provide?
Click to reveal answer
Answer
Dropdown options for select fields
Question
How do you add an admin menu item?
Click to reveal answer
Answer
Use menu.xml with add elements
Question
What interface provides config values?
Click to reveal answer
Answer
ScopeConfigInterface
Revision Notes
Key Takeaways
- 1. system.xml defines admin config sections, groups, fields
- 2. menu.xml defines admin menu items and hierarchy
- 3. Source models provide dropdown options; backend models handle save logic
- 4. Access config values via ScopeConfigInterface::getValue()
- 5. Config path format: section/group/field
Interview Tips
- • Explain the system.xml section/group/field hierarchy
- • Know how to create custom source and backend models
- • Be ready to add admin menu items and configuration sections
- • Discuss configuration scopes (default, website, store)
Cheat Sheet
system.xml: section → group → field
menu.xml: <add id="..." parent="..."/>
Source model: implements ArrayInterface
Backend model: extends AbstractBackend
Access: $this->scopeConfig->getValue('section/group/field')