Dependency Injection

 Dependency injection is a technique whereby one object supplies the dependencies of another object 

 What is Dependency Injection — Wikipedia

Dependency injection is a procedure where one object supplies the dependencies of another object. Dependency Injection is a software design approach that allows avoiding hard-coding dependencies and makes it possible to change the dependencies both at runtime and compile time.

There are many ways to inject objects

Constructor Injection - 

In this we can inject an object through the class constructor.

Example - 

<?php

   class Developer{

      private $skills;

      public function __construct($skills){

         $this->skills = $skills;

      }

      public function totalSkills(){

         return count($this->skills);

      }

   }

   $createskills = array["Drupal", "Zend", "JavaScript"];

   $p = new Developer($createskills);

   echo $p->totalSkills();

?>

Setter Injection - 

Where you can inject the object to your class through setter function.

<?php

   class Multilingual {

      private $language;

      public function setLanguage($language){

         $this->language = $language;

      }

   }

   $multi = new Multilingual();

   $language = array["Drupal","Zend","JavaScript"];

   $multi->setLanguage($language);

?>

Dependency Injection Drupal - 

As of Drupal 8, dependency injection is the preferred method for accessing and using services and should be used whenever possible. Rather than calling out to the global services container, services are instead passed as arguments to a constructor or injected via setter methods. This allows for a loose coupling of components, which makes things easier to test, and easier to replace with alternative implementations.

Dependency injection (DI) and the Symfony service container are important new development features of Drupal 8. However, even though they are starting to be better understood in the Drupal development community, there is still some lack of clarity about how exactly to inject services into Drupal 8 classes.

Example - 

$service = \Drupal::service('service_name');

1. injecting services into another of your own services

2. injecting services into non-service classes

3. injecting services into plugin classes

Services - 

Injecting services into your own service is very easy. Since you are the one defining the service, all you have to do is pass it as an argument to the service you want to inject. Imagine the following service definitions.

services:

    demo.demo_service:

        class: Drupal\demo\DemoService

    demo.another_demo_service:

        class: Drupal\demo\AnotherDemoService

        arguments: ['@demo.demo_service']


Here we define two services where the second one takes the first one as a constructor argument. So all we have to do now in the AnotherDemoService class is store it as a local variable.

class AnotherDemoService {

  /**

 * @var \Drupal\demo\DemoService

   */

  private $demoService;

  public function __construct(DemoService $demoService) {

    $this->demoService = $demoService;

  }

  // The rest of your methods

}

And that is pretty much it. It's also important to mention that this approach is exactly the same as in Symfony, so no change here.

Controllers - 

Controller classes are mostly used for mapping routing paths to business logic. They are supposed to stay thin and delegate heavier business logic to services. Many extend the ControllerBase class and get some helper methods to retrieve common services from the container. However, these are returned statically.

When a controller object is being created 'ControllerResolver::createController', the ClassResolver is used to get an instance of the controller class definition. The resolver is container aware and returns an instance of the controller if the container already has it. Conversely, it instantiates a new one and returns that. 

And here is where our injection takes place: if the class being resolved implements the ContainerAwareInterface, the instantiation takes place by using the static create() method on that class which receives the entire container. And our ControllerBase class also implements the ContainerAwareInterface.

/**

 * Defines a controller to list blocks.

 */

class BlockListController extends EntityListController {

  /**

   * The theme handler.

   *

   * @var \Drupal\Core\Extension\ThemeHandlerInterface

   */

  protected $themeHandler;

 

  /**

   * Constructs the BlockListController.

   *

   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler

   *   The theme handler.

   */

  public function __construct(ThemeHandlerInterface $theme_handler) {

    $this->themeHandler = $theme_handler;

  }

  /**

   * {@inheritdoc}

   */

  public static function create(ContainerInterface $container) {

    return new static(

      $container->get('theme_handler')

    );

  }

}

The EntityListController class doesn't do anything for our purposes here, so just imagine that BlockListController directly extends the ControllerBase class, which in turn implements the ContainerInjectionInterface.

As we said, when this controller is instantiated, the static create() method is called. Its purpose is to instantiate this class and pass whatever parameters it wants to the class constructor. And since the container is passed to create(), it can choose which services to request and pass along to the constructor. 

Then, the constructor simply has to receive the services and store them locally. Do keep in mind that it's bad practice to inject the entire container into your class, and you should always limit the services you inject to the ones you need. And if you need too many, you are likely doing something wrong.

We used this controller example to go a bit deeper into the Drupal dependency injection approach and understand how constructor injection works. There are also setter injection possibilities by making classes container aware, but we won't cover that here. Let's instead look at other examples of classes you may interact with and in which you should inject services.

2 comments:

Unknown said...

Nyc

Inwizards Software said...

Nice blog! I really loved reading through this Blog... Thanks for sharing such a very interesting post with us and keep blogging. Visit our website-
web and app development company
hire xamarin developers
hire .net developers
hire android developers

Write a program in PHP to reverse a number

A number can be written in reverse order. For example 12345 = 54321 <?php   $ num = 23456;   $ revnum = 0;   while ($ num > 1)   {   $...