Skip to content
intermediate Phase 20 · Module File Structure

Magento 2 di.xml

Global and area-specific di.xml, type configuration, preferences, virtual types, arguments, and plugin declarations.

1h
0 problems
Topic Progress 0%

di.xml Structure and Scopes

The di.xml file is the primary configuration for dependency injection in Magento 2.

Global vs area-specific:

etc/di.xml              # Global (all areas)
etc/frontend/di.xml     # Frontend only
etc/adminhtml/di.xml    # Admin only
etc/webapi_rest/di.xml  # REST API only
etc/webapi_graphql/di.xml # GraphQL only
etc/crontab/di.xml      # Cron only

Merge behavior:

  • Global di.xml loads first
  • Area-specific di.xml loads second
  • Area-specific takes precedence for same keys

Basic di.xml structure:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    
    <!-- Preferences -->
    <preference for="Interface" type="Implementation"/>
    
    <!-- Type configuration -->
    <type name="ClassName">
        <arguments>
            <argument name="param" xsi:type="string">value</argument>
        </arguments>
        <plugin name="name" type="PluginClass"/>
    </type>
    
    <!-- Virtual types -->
    <virtualType name="Alias" type="RealClass"/>
    
</config>

di.xml location per module:

app/code/Vendor/Module/
├── etc/
│   ├── di.xml              # Global
│   ├── frontend/
│   │   └── di.xml          # Frontend
│   ├── adminhtml/
│   │   └── di.xml          # Admin
│   └── webapi_rest/
│       └── di.xml          # REST API

Type Configuration and Arguments

The <type> element configures constructor arguments, plugins, and other settings for specific classes.

Type configuration:

<type name="Vendor\Module\Service\Processor">
    <arguments>
        <argument name="batchSize" xsi:type="number">100</argument>
        <argument name="timeout" xsi:type="number">30</argument>
        <argument name="enabled" xsi:type="boolean">true</argument>
        <argument name="apiKey" xsi:type="string">abc123</argument>
        <argument name="logger" xsi:type="object">Vendor\Module\Logger\CustomLogger</argument>
        <argument name="config" xsi:type="array">
            <item name="retry_count" xsi:type="number">3</item>
            <item name="mode" xsi:type="string">strict</item>
        </argument>
        <argument name="modes" xsi:type="array">
            <item name="0" xsi:type="string">active</item>
            <item name="1" xsi:type="string">inactive</item>
        </argument>
    </arguments>
</type>

Argument types:

<!-- String -->
<argument name="name" xsi:type="string">value</argument>

<!-- Number (int/float) -->
<argument name="count" xsi:type="number">42</argument>

<!-- Boolean -->
<argument name="flag" xsi:type="boolean">true</argument>

<!-- Object (class/interface) -->
<argument name="dep" xsi:type="object">Some\Class</argument>

<!-- Array -->
<argument name="items" xsi:type="array">
    <item name="key" xsi:type="string">value</item>
</argument>

<!-- Constant -->
<argument name="mode" xsi:type="const">Some\Class::CONSTANT</argument>

Extending existing type configuration:

<!-- Add argument to existing class -->
<type name="Magento\Catalog\Model\Product">
    <arguments>
        <argument name="customAttribute" xsi:type="string">value</argument>
    </arguments>
</type>

Virtual Types

Virtual types create named configurations of existing classes without creating new PHP classes.

Basic virtual type:

<virtualType name="LoggerForImport" type="Magento\Framework\Logger\Monolog">
    <arguments>
        <argument name="name" xsi:type="string">import.log</argument>
    </arguments>
</virtualType>

Virtual type with arguments:

<virtualType name="CustomLogger" type="Vendor\Module\Logger\Logger">
    <arguments>
        <argument name="logFile" xsi:type="string">custom.log</argument>
        <argument name="level" xsi:type="string">debug</argument>
        <argument name="handlers" xsi:type="array">
            <item name="stream" xsi:type="object">
                Magento\Framework\Logger\Handler\Stream
            </item>
        </argument>
    </arguments>
</virtualType>

Using virtual type as dependency:

<!-- Virtual type defined -->
<virtualType name="OrderLogger" type="Vendor\Module\Logger\FileLogger">
    <arguments>
        <argument name="filename" xsi:type="string">orders.log</argument>
    </arguments>
</virtualType>

<!-- Inject virtual type into class -->
<type name="Vendor\Module\Service\OrderService">
    <arguments>
        <argument name="logger" xsi:type="object">OrderLogger</argument>
    </arguments>
</type>

Virtual type benefits:

  • No new PHP classes needed
  • Different configurations of same class
  • No preference conflicts
  • Can override any class configuration
  • Easy to test with different configurations

Plugin Declarations

Plugins (interceptors) are declared in di.xml to modify class method behavior.

Basic plugin declaration:

<type name="Magento\Catalog\Model\ProductRepository">
    <plugin name="vendor_product_after_save"
            type="Vendor\Module\Plugin\ProductAfterSave"
            sortOrder="10"/>
</type>

Plugin attributes:

  • name - Unique identifier across all plugins for this class
  • type - Plugin class implementing before/after/around methods
  • sortOrder - Execution order (lower = first)
  • disabled - Set to true to disable
  • shared - Whether plugin instance is shared (default: false)

Multiple plugins:

<type name="Magento\Catalog\Model\ProductRepository">
    <plugin name="first_plugin" type="...\FirstPlugin" sortOrder="10"/>
    <plugin name="second_plugin" type="...\SecondPlugin" sortOrder="20"/>
    <plugin name="third_plugin" type="...\ThirdPlugin" sortOrder="30"/>
</type>

Plugin execution order:

around(10) → before(10) → before(20) → Method → after(20) → after(10)

Disabling plugins:

<type name="Magento\Catalog\Model\ProductRepository">
    <plugin name="vendor_product_after_save" disabled="true"/>
</type>

Plugin class example:

<?php
namespace Vendor\Module\Plugin;

class ProductAfterSave
{
    public function beforeSave($subject, $product)
    {
        // Before plugin
        return [$product];
    }
    
    public function afterSave($subject, $result)
    {
        // After plugin
        return $result;
    }
    
    public function aroundSave($subject, $proceed, $product)
    {
        // Around plugin
        $result = $proceed($product);
        return $result;
    }
}

Quiz

1. What takes precedence when merging global and area-specific di.xml?

Question 1 options

2. What xsi:type is used for class/object arguments?

Question 2 options

3. How do you disable a plugin in di.xml?

Question 3 options

Flashcards

Question

What are the five di.xml scopes?

Answer

global, frontend, adminhtml, webapi_rest, webapi_graphql, crontab

Question

What xsi:type creates a configured variant of a class?

Answer

virtualType

Question

How do you create a new instance instead of shared?

Answer

Set shared="false" on the type element

Question

What element declares plugins in di.xml?

Answer

<plugin> inside a <type> element

Revision Notes

Key Takeaways

  • 1. di.xml exists in global and area-specific scopes
  • 2. Area-specific takes precedence over global
  • 3. Type configures constructor arguments and plugins
  • 4. Virtual types create configured variants without new classes
  • 5. Plugin sortOrder controls execution order
  • 6. Arguments support string, number, boolean, object, array, const

Interview Tips

  • Explain the difference between global and area-specific di.xml
  • Describe how virtual types work with examples
  • Discuss plugin declaration and ordering
  • Know all argument types in di.xml
  • Explain when to use type vs virtual type vs preference

Cheat Sheet

di.xml Cheat Sheet

Scopes: global, frontend, adminhtml, webapi_rest, webapi_graphql, crontab

Elements:

<preference for="Interface" type="Implementation"/>
<type name="Class">
    <arguments>
        <argument name="param" xsi:type="string">value</argument>
    </arguments>
    <plugin name="name" type="Plugin" sortOrder="10"/>
</type>
<virtualType name="Alias" type="Class"/>

Argument Types:
string, number, boolean, object, array, const

Plugin Order:
around(10) → before(10) → Method → after(10)