In Magento 1.x, it was possible to use the .xml
file to include custom configuration options that might be necessary for an extension. This is no longer possible with Magento 2 because the XML files are all validated against a schema and anything other than predefined options are not allowed. To solve this, it is possible to generate your own custom XML file to set up the parameters that you need. This also allows other extensions to define settings as the output is generated from all modules that have this file configured.
In order to use your own XML configuration file, it is important that you generate a valid schema (XSD) file that will be used to validate the XML files when they are merged.
The following steps show you how to define a custom XML configuration file for your module:
Reader
for the XML file and define the name of the file that should be read from all modules:Model/Sample/Reader.php
<?php namespace GenmatoSampleModelSample; use MagentoFrameworkConfigReaderFilesystem; use MagentoFrameworkConfigFileResolverInterface; use MagentoFrameworkConfigConverterInterface; use GenmatoSampleModelSampleSchemaLocator; use MagentoFrameworkConfigValidationStateInterface; class Reader extends Filesystem { protected $_idAttributes = [ '/table/row' => 'id', '/table/row/column' => 'id', ]; /** * @param FileResolverInterface $fileResolver * @param ConverterInterface $converter * @param SchemaLocator $schemaLocator * @param ValidationStateInterface $validationState * @param string $fileName * @param array $idAttributes * @param string $domDocumentClass * @param string $defaultScope */ public function __construct( FileResolverInterface $fileResolver, ConverterInterface $converter, SchemaLocator $schemaLocator, ValidationStateInterface $validationState, $fileName = 'sample.xml', $idAttributes = [], $domDocumentClass = 'MagentoFrameworkConfigDom', $defaultScope = 'global' ) { parent::__construct( $fileResolver, $converter, $schemaLocator, $validationState, $fileName, $idAttributes, $domDocumentClass, $defaultScope ); } }
Reader
must know where to find the schema file:Model/Sample/SchemaLocator.php
<?php
namespace GenmatoSampleModelSample;
use MagentoFrameworkConfigSchemaLocatorInterface;
use MagentoFrameworkConfigDomUrnResolver;
class SchemaLocator implements SchemaLocatorInterface
{
/** @var UrnResolver */
protected $urnResolver;
public function __construct(UrnResolver $urnResolver)
{
$this->urnResolver = $urnResolver;
}
/**
* Get path to merged config schema
*
* @return string
*/
public function getSchema()
{
return $this->urnResolver->getRealPath('urn:genmato:module:Genmato_Sample:/etc/sample.xsd');
}
/**
* Get path to pre file validation schema
*
* @return string
*/
public function getPerFileSchema()
{
return $this->urnResolver->getRealPath('urn:genmato:module:Genmato_Sample:/etc/sample.xsd');
}
}
Model/Sample/Data.php
<?php namespace GenmatoSampleModelSample; use MagentoFrameworkConfigDataScoped; use GenmatoSampleModelSampleReader; use MagentoFrameworkConfigScopeInterface; use MagentoFrameworkConfigCacheInterface; class Data extends Scoped { /** * Scope priority loading scheme * * @var array */ protected $_scopePriorityScheme = ['global']; /** * @param Reader $reader * @param ScopeInterface $configScope * @param CacheInterface $cache * @param string $cacheId */ public function __construct( Reader $reader, ScopeInterface $configScope, CacheInterface $cache, $cacheId = 'sample_config_cache' ) { parent::__construct($reader, $configScope, $cache, $cacheId); } }
etc/sample.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="table"> <xs:complexType> <xs:sequence> <xs:element name="row" maxOccurs="unbounded" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element name="column" maxOccurs="unbounded" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="label"> <xs:annotation> <xs:documentation>from first xml from second xmlthey apear in both xmls with the same path and id and second one overrides the value for `attr1` from first xml from first xml</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> <xs:attribute type="xs:string" name="id" use="optional"/> <xs:attribute type="xs:byte" name="sort" use="optional"/> <xs:attribute type="xs:string" name="attr1" use="optional"/> <xs:attribute type="xs:string" name="disabled" use="optional"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute type="xs:string" name="id" use="optional"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
etc/sample.xml
<?xml version="1.0"?> <table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:genmato:module:Genmato_Sample:/etc/sample.xsd"> <row id="row1"> <column id="col1" sort="10" attr1="val1"> <label>Col 1</label> </column> </row> <row id="row2"> <column id="col1" sort="10" attr1="val1"> <label>Col 1</label> </column> <column id="col2" sort="20" disabled="true" attr1="val2" > <label>Col 2</label> </column> <column id="col3" sort="15" attr1="val1"> <label>Col 3</label> </column> </row> </table>
Controller/Index/Sample.php
<?php
namespace GenmatoSampleControllerIndex;
use MagentoFrameworkAppActionAction;
use MagentoFrameworkAppActionContext;
use MagentoFrameworkViewResultPageFactory;
use GenmatoSampleModelSampleDataFactory;
class Sample extends Action
{
/**
* @var PageFactory
*/
private $resultPageFactory;
/** @var DataFactory $dataReader */
private $dataReader;
/**
* @param Context $context
* @param PageFactory $resultPageFactory
* @param DataFactory $dataReader
*/
public function __construct(
Context $context,
PageFactory $resultPageFactory,
DataFactory $dataReader
)
{
$this->dataReader = $dataReader;
parent::__construct($context);
}
/**
* Renders Sample
*/
public function execute()
{
$myConfig = $this->dataReader->create();
print_r($myConfig->get());
}
}
bin/magento cache:clean
http://example.com/sample/index/sample/
The configuration reader defines the file that is used in the ($fileName = 'sample.xml'
) constructor. Make sure that the filename used is unique; otherwise, configuration data from another module will be merged and validation will fail as it won't match the schema that you defined. A solution could be to use <vendor>_<module>.xml
as the filename.
In the constructor, SchemaLocator
is also defined; this will define the schema (XSD file) that is used to validate the XML. To be able to get the schema file independent from where the module is installed (vendor/
or app/code
), the schema location is built from the defined URN: urn:genmato:module:Genmato_Sample:/etc/sample.xsd
. This URN is parsed and translated to the directory where the module is installed, which is done through ComponentRegistrar
, and the module location is registered in registration.php
as described in Chapter 7, Creating Magento 2 Extensions – the Basics.
It is possible to get all data using the read()
method on the Reader
class, this will result in re-reading and merging all XML files, which will impact every request. This can delay the website; therefore, the Data
class is added. Here, Reader
is injected through the constructor. To get the data, you can call the get()
method of the Data
class. This will read and merge all XML files if they are not cached and return the cached version when available. If you don't supply an argument to the get()
method, it will return all data, but it's also possible to specify a node that you would like.
The Data
class can be added everywhere that you need to get your configuration data; for this, you add GenmatoSampleModelSampleDataFactory
to the constructor. This autogenerated class allows you to instantiate your configuration data class:
$myConfig = $this->dataReader->create();
This gets a value from the configuration:
$myConfig->get('<node>');
3.146.176.145