Dependency Injection and Drupal 8

Drupal is changing a lot in 8.x, and one of those major changes is adding the Drupal Dependency Container. What is that exactly?

Explain Yourself

  • Dependency injection is a design pattern used to dynamically load service objects, such as a mail delivery service.
  • Normally an object decides what service classes it will use – it will instantiate an object of a given class, then use it. In dependency injection the object will call the injection container which will provide it suitable classes depending on runtime configuration.
  • Sometimes called ‘Inversion of control’
  • The injector is often called a container.

Why all the fuss?

  • Allows selection from multiple potential interfaces at runtime
  • Creates highly pluggable systems – easily switch out caching backends for example.
  • Great for testing – no need to bootstrap or live connections to external services, just give the subsystem a stub implementation. Components can be tested in isolation.

How does it work?

  • Specify the interface for the dependency
  • Let the container object select the implementation

Types of Injection

  • Constructor injection – most common, pass in service object via constructor.
  • Setter injection – good for optional dependencies
  • Property injection – set public attributes directly.

Drupal’s DIC Implementation

One of the first things drupal_handle_request() does is instantiate an object of class DrupalKernel, which is extended from Symfony’s HttpKernel class Kernel.

Getting a service from the container:

$request = drupal_container()->get('request');
$path = $request->attributes->get('system_path');

To create a new service we implement the Bundle class:

<?php
// This file should be located at: my_module/lib/Drupal/my_module/MyModuleBundle.php

/**
* @file
* Definition of Drupal\my_module\MyModuleBundle.php.
*/
namespace Drupal\my_module;
use \Symfony\Component\HttpKernel\Bundle\Bundle;
use \Symfony\Component\DependencyInjection\ContainerBuilder;
// This line is only needed if actually using the Reference class as below.
use \Symfony\Component\DependencyInjection\Reference;

/**
* The bundle for my_module.module.
*/
class MyModuleBundle extends Bundle {

public function build(ContainerBuilder $container) {
// This registers the specified class to be lazy-instantiated when
// mymodule.some_service is requested from the container, with a constructor
// parameter of the container itself.
$container->register('my_module.some_service', 'Drupal\mymodule\SomeClassHere')
->addArgument(new Reference('service_container'));
}
}
?>

You can see the core implementation of this in lib/Drupal/Core/CoreBundle.php. Some of the services registered include:

  • Configuration system
  • Database connection
  • Queue system
  • Path alias manager
  • Entity manager
  • HTTP Kernel
  • Language manager
  • Twig

Thats a pretty basic overview of Dependency Injection and how it is implemented in Drupal. Lots more information can be found in the links below.

References

By Sam

Drupal developer from Perth, Western Australia. I love programming, gaming, the Internet, growing vegetables and hiking.

1 comment

Leave a comment

Your email address will not be published. Required fields are marked *