DEPENDENCY INJECTION (DI) IN MAGENTO 2

Dependency simply means that something is dependent on something like you are dependent on school for education. The same goes for programming – if we create a class, it can depend on the objects created inside the class.

Injection simply means providing something or injecting something by a third party.

Before starting with dependency injection, we want to give you a simple example for you to get the basic idea of dependency injection.

Carmaker companies make cars, and tires are an essential part of any vehicle. So, what carmakers can do is they can start making tires, but that’s what they don’t do. As tires are an essential part, instead of making tires themselves, they purchase tires from other vendors according to their needs and fit them on their cars. It makes their work easy. The carmakers are dependent on tire companies, and the tire company provides tires according to their car model. Thus the construction of car tires is more independent than the construction of cars, i.e., it decouples the process of the construction of its dependency (i.e., the whole Car).

The same goes for Dependency Injection – Dependency Injection is a design pattern that allows an object (let’s say object A) to declare its dependencies to another external object (let’s say object B) that supplies those dependencies. The dependencies declared by object A are usually class interfaces and the B provides the concrete implementations for those interfaces.

A technical example

This allows for loose code coupling because object A no longer needs to be concerned with initializing its own dependencies. Instead, object B decides which implementations to provide to object A based on a configuration or desired behavior.

Several latest software application frameworks support Dependency Injection, including TypeScript, Spring, Google Guise, Microsoft Managed Extensibility Framework (MEF), etc.

Magento 2 uses Dependency Injection to replace functionality provided by the Mage class in Magento 1.x.

Note: Dependency Injection decouples your class from the construction of its dependency.

Let’s take an example:

(1). Customer Class

class Customer
{
    private $firstName;
    private $lastName;
    public function __construct($firstName, $lastName) {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }
    public function getFirstName() {       return $this->firstName;
    } 
    public function getLastName() {
      return $this->lastName;
    }
 } 

(2.)Here we created an object for the above class.

class CustomerInfo
{
   private $customer;
   public function __construct($customerFirstName, $customerLastName) {
       $this->customer = new Customer($customerFirstName, $customerLastName);.
   }
   public function getCustomer() {
      return $this->customer;
   } 
}

The above code will work absolutely fine. It will return the first & last name without any issues. But the Customer class is tightly coupled with the CustomerInfo class. That’s where the problem is. It is not easy to maintain such a tightly coupled code. 

Suppose you add a new parameter to the constructor of the Customer class. In that case, you have to modify every class where you had created a Customer object with the new operator, which is not as simple as it looks for large applications. In this example, we use a customer object only in one class named CustomerInfo, but think of a scenario when we are using a customer object in 100s of classes, then updating your code in all 100 classes isn’t a simple job. So, this code is fine in terms of working but is not maintainable.

Dependency Injection solves these issues by injecting dependencies through the dependent class Constructor. So, look at the same code another way now.

Again we will create an object of Customer class, but our approach will be slightly different this time. We will inject the Customer through the constructor. See the difference.

class CustomerInfo {     private $customer; 
    public function __construct(Customer $customer) {
       $this->customer = $customer;
    }     public function getCustomer() {
      return $this->customer; 
    } 
}

In the above code, instead of instantiating dependency with the new operator in the above code, we defined it in a __construct parameter. Hence, it is known as Automatic Dependency Injection.

By using Automatic Dependency Injection (ADI), the object doesn’t need to look for another dependent object (It is derived from Constructor Injection )

Injection Types Used In Magento

You can inject dependency in a particular class by using two types of Dependency Injection in Magento 2

1. Constructor Injection

2. Method Injection

1. Constructor Injection

In this type of DI, all you need to do is add a parameter in the class constructor to inject the dependency.

For example, In a Helper class that is in Bizspice/Diexample/Helper/Data.php file with the following code:

<?php namespace Bizspice\Diexample\Helper;
use \Magento\Framework\App\Helper\AbstractHelper;
class Data extends AbstractHelper >
{
    public function DemoClass() {
       //Your Code Here
    }
} 

In the above Helper Class, We have created a function DemoClass() that can be called anywhere in Magento 2 using the Constructor Injection.

<?php 
class DependentClass
{    public function __construct(Bizspice\Diexample\Helper\Data $helper) {
       $this->helper = $helper;
   }
   public function MyFunction() { 
        $this->helper->DemoClass(); 
   } 
} 

Here in DependentClass declares its dependency on Bizspice\Diexample\Helper\Data through constructor [public function __construct(Bizspice\Diexample\Helper\Data $helper)] and calledDemoClass function in the class

2. Method Injection

In this type of DI, we pass dependency as a method parameter to use in the class. Method injection can be used best when the dependency may vary on each method call. When an object requires performing specific actions on a dependency that can’t be injected, it is recommended to use the Method Injection.

<?php namespace Bizspice\ModuleName\Observer\Product;
use Magento\Framework\Event\ObserverInterface;
class Data implements ObserverInterface 
{
   public function execute(Magento\Framework\Event\Observer $observer) { 
      //Your Code Here
    } 
}

In the above code for Method Injection, the execute() method in Data class is dependent on the Magento\Framework\Event\Observer class.i.e

public function execute(Magento\Framework\Event\Observer $observer)