Configuring an Existing Type

The type node changes how a class you do not own is constructed, and array items merge by name so you can add a single entry.

Syntax<type name="Magento\Framework\Console\CommandList"><arguments>...</arguments></type>

A <type> node configures a class that already exists. You do not subclass it and you do not copy it: you name it and supply arguments. Every enabled module's di.xml is merged into one configuration, so a <type> node in your module reaches a class that lives in vendor/magento.

Arrays merge by item name

The merge happens item by item. An <item> with a new name is added to the array; an <item> that reuses an existing name replaces that one entry and leaves the rest alone. That is why registering one more validator, reader or console command takes three lines instead of restating the whole list. Arguments you do not mention keep whatever value they already had.

sortOrder

Items otherwise stay in merge order, which follows module load order. Magento sorts the items of an array argument as soon as at least one item declares a sortOrder, an attribute allowed on string and object items. Several older composites in core take a different shape instead: each entry is a nested array holding reader and sortOrder items, and the receiving class sorts them in PHP. The two conventions are not interchangeable, so copy the shape the surrounding items already use.

Applying and checking it

Run bin/magento cache:clean config after the edit, or bin/magento setup:di:compile in production. Then read the merged result with bin/magento dev:di:info instead of assuming your item landed where you expected.

Example

Example · xml
<?xml version="1.0"?>
<!-- app/code/Vendor/Module/etc/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="vendor_module_export" xsi:type="object">Vendor\Module\Console\Command\ExportCommand</item>
            </argument>
        </arguments>
    </type>
</config>

When to use it

  • Register a console command, reader or validator from your module into a core composite.
  • Lower the database deadlock retry count on a store that should fail fast.
  • Place your entry ahead of an existing one in an array argument with sortOrder.
  • Point one existing array entry at your own class without touching a core file.

More examples

Change one argument and leave the others alone

app/etc/di.xml configures this class with cache set to Magento\Framework\App\Cache\Type\Collection, cacheIdPrefix set to collection_ and cacheLifetime set to 86400. Naming only cacheLifetime cuts a cached collection result down to an hour and leaves the other two arguments at their configured values, because arguments merge per argument name. Nothing is visible on the storefront; cached collection results simply expire sooner. Run bin/magento cache:clean config in developer mode, or bin/magento setup:di:compile in production.

Example · xml
<?xml version="1.0"?>
<!-- app/code/Vendor/Module/etc/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Data\Collection\Db\FetchStrategy\Cache">
        <arguments>
            <argument name="cacheLifetime" xsi:type="string">3600</argument>
        </arguments>
    </type>
</config>

The two sortOrder shapes core uses

Two real excerpts, so you can recognise both. In the first, sortOrder is an attribute and the receiving constructor just takes an array of objects. In the second, every entry is an array of two items and Magento\Framework\Communication\Config\CompositeReader runs its own usort on the sortOrder key. Adding an entry in the wrong shape gives the class something it cannot use, so match the neighbours.

Example · xml
<!-- The attribute form: the framework sorts the items for you. -->
<!-- app/etc/di.xml, Magento\Framework\MessageQueue\Consumer\Config\CompositeValidator -->
<argument name="validators" xsi:type="array">
    <item name="requiredFields" xsi:type="object" sortOrder="10">Magento\Framework\MessageQueue\Consumer\Config\Validator\RequiredFields</item>
    <item name="fieldTypes" xsi:type="object" sortOrder="20">Magento\Framework\MessageQueue\Consumer\Config\Validator\FieldsTypes</item>
</argument>

<!-- The nested form: the receiving class sorts the array itself. -->
<!-- app/etc/di.xml, Magento\Framework\Communication\Config\CompositeReader -->
<argument name="readers" xsi:type="array">
    <item name="xmlReader" xsi:type="array">
        <item name="reader" xsi:type="object">Magento\Framework\Communication\Config\Reader\XmlReader</item>
        <item name="sortOrder" xsi:type="string">10</item>
    </item>
    <item name="envReader" xsi:type="array">
        <item name="reader" xsi:type="object">Magento\Framework\Communication\Config\Reader\EnvReader</item>
        <item name="sortOrder" xsi:type="string">20</item>
    </item>
</argument>

shared: the attribute you usually leave out

Without the attribute, the type's own shared setting applies, and that is true unless the class is declared as <type name="..." shared="false"/> somewhere. So the first two lines behave identically. Reach for shared="false" on builders and other objects that carry mutable state; core does it for Magento\Framework\Api\SearchCriteriaBuilder in app/etc/di.xml.

Example · xml
<!-- app/code/Vendor/Module/etc/di.xml -->
<!-- Shorthand -->
<argument name="writer" xsi:type="object">Vendor\Module\Model\Export\Writer</argument>

<!-- Longhand: the same thing, written out -->
<argument name="writer" xsi:type="object" shared="true">Vendor\Module\Model\Export\Writer</argument>

<!-- A fresh instance for every injection point -->
<argument name="writer" xsi:type="object" shared="false">Vendor\Module\Model\Export\Writer</argument>

Discussion

  • Be the first to comment on this lesson.