What’s Dependency Injection in Magento 2® All About

Magento2 will be introducing some amazing new features and functionalities, empowering developers to streamline customization tasks, improve load time and more. Most significantly, it will replace Magento 1.x Mage class with dependency injection design pattern.
This post is intended to provide resourceful insight on Magento’s 2 dependency injection concept.

An Overview of Dependency Injection

Over the last few years, dependency injection (also referred to as DI) has gained popularity because of the increasing demand for unit and integration testing. However, dependency injection can be a lot useful when implemented in Magento 2, rather than used for writing unit tests alone. The primary reason behind introducing dependency injection in Magento 2 is to reduce code dependencies.
Code dependencies often restrict developers from reusing the code and moving components to some other project a challenging task. As your code grows in size managing dependencies will become difficult for you, however, dependency injection helps minimize dependencies of one component on the other.

Wondering how?
Let’s say you have two modules: Module A and Module B. In case, Module A is a high-level module that needs to access certain functionality present in Module B (a low-level detailed module) it controls. This means that Module A is dependent on Module B. As time pass by it may become dependent on several other low-level modules making Module A rigid. However, you can resolve this issue with help of dependency injection that helps make Module A independent of the lower-level Module B it controls, and make it reusable.
In nutshell, dependency injection means that all dependencies are passed to the object, instead of making the object create or find some dependency.
However, there is a downside to using DI: to remove dependencies it makes the code larger than the actual code. In order to tackle this problem it uses an injection container, called as Object Manager in Magento 2.

How to Configure Dependency Injection?

In order to configure dependency injection in Magento 2 you’ll need to use Object Manager, which requires the following configurations:
• Class definitions: They help define the type and number of dependencies. Luckily, Magento use the constructor signature to compile class dependencies automatically. In essence, it helps determine dependencies that should be passed to an object.
• Instance configurations: Specifies how objects are instantiated, and help define their lifecycle.
• Abstraction-implementation mappings: Define the sort of implementation that needs to be used based on the request to an interface

How to Use Dependency Injection?

In order to use dependency injection, you will have to become familiar with its types, and the objects used in this approach.

1. Types of Dependency Injection

There are two ways that helps in introducing dependencies, as listed below:

1.1 Constructor injection

Constructor injection, as the name implies, passes dependencies via a class constructor. This type of DI can be used for the service dependencies of an object and the optional ones as well. For expensive optional dependencies proxy pattern is used; the best part part is that proxy gets automatically generated and thus do not require you to mess around with the coding part.
Here is an example of a simple proxy (that you can declare in di.xml):

<type name="Magento\Backend\Model\Config\Structure\Element\Iterator\Field" shared="false">
    <arguments>
        <argument name="groupFlyweight" xsi:type="object">Magento\Backend\Model\Config\Structure\Element\Group\Proxy</argument>
    </arguments>
</type>
<?php
class Foo
{
    protected $_bar;
    public function __construct(Bar $bar) {
        $this->_bar = $bar;
    }
    public function execute() {
        
        //some code
        $this->_bar->execute();
        
        //some code
        
    }
}
$bar = new Bar();
$foo = new Foo($bar);
$foo->execute();

1.2 Method injection

This type of DI is used for API parameters (or API objects) your object acts on. Below is an example where $command is used as the API parameter and declares $itemFactory and $menu as service dependencies:

<?php
namespace Magento\Backend\Model\Menu;
class Builder
{
    
    /**
     * @param \Magento\Backend\Model\Menu\Item\Factory $menuItemFactory
     * @param \Magento\Backend\Model\Menu $menu
     */
    public function __construct(Magento\Backend\Model\Menu\Item\Factory $menuItemFactory,
     // Service dependency
    Magento\Backend\Model\Menu $menu
    
    // Service dependency
    ) {
        $this->_itemFactory = $menuItemFactory;
        $this->_menu = $menu;
    }
    public function processCommand(\Magento\Backend\Model\Menu\Builder\CommandAbstract $command)
     // API param
    {
        if (!isset($this->_commands[$command->getId() ])) {
            $this->_commands[$command->getId() ] = $command;
        } else {
            $this->_commands[$command->getId() ]->chain($command);
        }
        return $this;
    }
}

2. Types of Objects used in DI

Apart from understanding the types of dependency injection, you will also need to know about the type of objects that are injected, such as:

2.1 Injectable objects (injectables):

These are also referred to as value objects and global system services. These objects don’t have any identity and don’t need any user’s input when they’re created. They can be created using object manager, for example, database adapter, layout model, etc.

2.2 Non-injectable objects (non-injectables):

Unlike injectable objects, non-injectable objects have an identity. They are data objects or we can call them primitive values, which have an identity. Some examples of non-injectables are products, cart items, users, and so on. They can’t be created using object manager, and to created them you need to request to their factory. For example, let’s say you want to load various products, in that case your code will rely on the product factory, and via that object you will have to call create() method having products identity (you’re trying to load).

Let’s now have a look at the types of utility objects in more detail:
Factories (for factory objects): They are special objects used for only a single purpose: to create non-injectable objects. It even relies upon the object manager. Most significantly, they are used for extricating object manager from business code:

<?php
class Magento\Core\Model\Config\BaseFactory
{
    protected $_objectManager;
    public function __construct(Magento\Framework\ObjectManager $objectManager) {
        $this->_objectManager = $objectManager;
    }
    public function create($sourceData = null) {
        return $this->_objectManager->create('Magento\Core\Model\Config\Base', array('sourceData' => $sourceData));
    }
}

Proxies (for proxy objects): This type of utility object is utilized for lazy loading of the “optional constructor arguments” or expensive dependencies (as we had discussed above).

<?php
class Magento_Core_Model_Mailer
{
    public function __construct(Magento_Mail_Adapter $adapter,
     //... the list of expensive dependencies)
    {
        $this->_adapter = $adapter; . . .
    }
    public function send(Magento_Core_Model_Mail $letter) {
        $this->_adapter->send($letter->toString()); . . .
    }
}
class Magento_Core_Model_Mailer_Proxy extends Magento_Core_Model_Mailer
{
    public function __construct(Magento_ObjectManager $objectManager) {
        $this->_objectManager = $objectManager;
    }
    public function send(Magento_Core_Model_Mail $letter) {
        $this->_objectManager->get('Magento_Core_Model_Mailer')->send($letter);
    }
}
class Magento_Sales_Model_Order_Processor
{
    public function __construct(Magento_Core_Model_Mailer $mailer) {
        $this->_mailer = $mailer;
    }
    public function processSomeEvent($event) {
        $order = $event->getData('order');
        $shouldSendMail = $event->getData('shouldMail'); . . . if ($shoudSendMail) {
            $this->_mailer->send($order);
        }
    }
}

For this code, you need to use the configuration file to replace an existing class with a proxy, as follows:

<config>
    <type name="Magento_Sales_Order_Processor">
        <param name="instance">
    </type>
</config>

3. Type Configurations

Type defines dependency scope which includes all of the Magento modules and module area.

3.1 Specify Types: It tells about dependencies injection by type, as shown in the example below:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <type name="Magento\Core\Model\Session" />
        <!-- Default instance of Magento\Core\Model\Session type. Exists by default, can be omited. -->
        <virtualType name="moduleConfig" type="Magento\Core\Model\Config">
            <!-- Instance with global name "config" of Magento\Core\Model\Config type -->
            <arguments>
                <argument name="type" xsi:type="string">system</argument>
            </arguments>
        </virtualType>
        <type name="Magento\Core\Model\App">
            <arguments>
                <argument name="config" xsi:type="object">moduleConfig</argument>
            </arguments>
        </type>
    </type>
</config>

As you can see, the above example displays three configuration types such as:
1. config– virtual type extending Magento/Core/Model/Config
2. moduleConfig – extends Magento/Core/Model/Config
3. Magento/Core/Model/App – retrieves moduleConfig as a dependency

3.2 Arguments

They are injected into an instance of a class when it is created. Besides this, parameter name should match with the constructor parameters of configured class.
Parameter – they are declared in the constructor signature variable
Argument- it’s just a value used at the time when a class is being created.

Wrapping Up!

I hope reading this post will help you provide detailed view on all key aspects of dependency injection, so as to make it easy for you to implement this approach in Magento 2.

Written by Maria Mincey

Maria Mincey is qualified web development professional who is great at delivering focus in her writings. She meets expectations for OSSMedia, a Magento development company which also giving proficient WordPress, Drupal and Joomla improvement administrations.

Website: http://www.ossmedia.com/

One thought on “What’s Dependency Injection in Magento 2® All About

Comments are closed.