Magento 2 – How to Read from Configuration Tree

configurationmagento2

What's "the right" way to read from a merged module XML configuration tree in Magento 2.

For example, in Magento 2, many modules have a pdf.xml configuration file

./Bundle/etc/pdf.xml
./Downloadable/etc/pdf.xml
./GroupedProduct/etc/pdf.xml
./Sales/etc/pdf.xml
./Tax/etc/pdf.xml
./Weee/etc/pdf.xml

It's my assumption, that similar to Magento 1, these files are all merged into a single tree for reading. In Magento 1, you'd ready from the merged configuration tree with a config object

$config = Mage::getConfig();
$config->getNode('path/to/node');

It's not clear how a developer should fetch data from the merged pdf.xml files. The dev docs has some good raw information about the new configuration system, but no straight forward examples of code that's equivalent to the above code in Magento 1.

I can think of half a dozen ways to do this using plain old PHP or the Magento 2 objects I know about — I'm interested in the "according to hoyle" way the Magento 2 core team does this when they need to (or, if there isn't one standard way, and it depends on which XML section you're reading from)

Best Answer

Every config type has a config class, with associated Reader, Convertor, and SchemaLocator classes. Those classes are responsible for finding, opening, and converting the XML data for its respective file into a usable format. (Technically it doesn't have to be XML, as long as the Reader can parse it, but that's what Magento 2 uses internally.)

Unlike Magento 1, Magento 2 does not load and merge all config files together, so there's no generic way of loading any arbitrary path from any arbitrary config type. It only loads what's necessary, from the appropriate areas for the current request, when the code actually asks for it.

This is covered in Unit 1 of the Fundamentals course, and one of the exercises is creating a custom config type.

You mention pdf.xml files specifically. That's defined in the sales module. Let's start in the sales di.xml. Here's where the config type is set up:

<type name="Magento\Sales\Model\Order\Pdf\Config\Reader">
    <arguments>
        <argument name="fileName" xsi:type="string">pdf.xml</argument>
        <argument name="converter" xsi:type="object">Magento\Sales\Model\Order\Pdf\Config\Converter</argument>
        <argument name="schemaLocator" xsi:type="object">Magento\Sales\Model\Order\Pdf\Config\SchemaLocator</argument>
    </arguments>
</type>
<virtualType name="pdfConfigDataStorage" type="Magento\Framework\Config\Data">
    <arguments>
        <argument name="reader" xsi:type="object">Magento\Sales\Model\Order\Pdf\Config\Reader</argument>
        <argument name="cacheId" xsi:type="string">sales_pdf_config</argument>
    </arguments>
</virtualType>
<type name="Magento\Sales\Model\Order\Pdf\Config">
    <arguments>
        <argument name="dataStorage" xsi:type="object">pdfConfigDataStorage</argument>
    </arguments>
</type>

The first type node sets the Reader's filename and associated Convertor and SchemaLocator classes. The pdfConfigDataStorage virtual type attaches that reader class to an instance of Magento\Framework\Config\Data. And finally, the last type attaches that config data virtual type to the Magento\Sales\Model\Order\Pdf\Config class, which is used for actually reading values in from those pdf.xml files.

So dependency injection pulls it all together, but the part you'll actually be referencing is the main Config class Magento\Sales\Model\Order\Pdf\Config. That class gives you an interface to the Reader, with methods getRenderersPerProduct and getTotals exposing the parsed XML data. You could also extend or implement your own Config class using the same Reader, if you wanted to get at the XML data in a way that class itself does not allow.

To see this Config class in use, check out $pdfConfig in Magento\Sales\Model\Order\Pdf\AbstractPdf.

The same technique and classes can be used to create any form of custom config files. You'll need those four class types (Config, Reader, Converter, SchemaLocator), an .xsd file defining the file schema, and of course your configuration xml itself.