Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Inject a service from the service container

Inject a Service in Drupal 8

Is a good practice to inject a service whenever is possible.

You can verify the service name by:

Looking at the Drupal Static Service Container wrapper class.

Reading the code on the Drupal Class you can find the httpClient method:

  /**
   * Returns the default http client.
   *
   * @return \GuzzleHttp\Client
   *   A guzzle http client instance.
   */
  public static function httpClient() {
    return static::getContainer()->get('http_client');
  }

Drupal class => https://api.drupal.org/api/drupal/core%21lib%21Drupal.php/class/Drupal/8

Taking advanage of Drupal Console debugging capabilities

$ drupal container:debug 

If you do not want to see the full list of services you can use | grep http

$ drupal container:debug | grep http

But you may do not know the service name, then I higly recommend you to use peco interactive filtering tool

$ drupal container:debug | peco | awk -F ' ' '{print $1}' | xargs drupal container:debug

You can find peco at https://github.com/peco/peco

Inject the service

Now that you know the service name http_client

Inject into a Class (Controller, Form, Plugin Block, etc)

 /**
   * Guzzle Http Client.
   *
   * @var GuzzleHttp\Client
   */
  protected $httpClient;

 /**
   * Constructs a new Class.
   *
   * @param \GuzzleHttp\Client $http_client
   *   The http_client.
   */
  public function __construct(
    Client $http_client
  ) {
    $this->httpClient = $http_client;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('http_client')
    );
  }

Inject a service into a service Class

// modules/custom/example/example.services.yml
services:
  example.default:
    class: Drupal\example\DefaultService
    arguments: ["@http_client"]

// modules/custom/example/src/DefaultService.php
 /**
   * GuzzleHttp\Client definition.
   *
   * @var GuzzleHttp\Client
   */
  protected $http_client;
  /**
   * Constructor.
   */
  public function __construct(Client $http_client) {
    $this->http_client = $http_client;
  }

NOTE: If you want to take full advantaje of DI, you must be injecting the interface, instead of the concrete class.

@rg-viza

This comment has been minimized.

Copy link

@rg-viza rg-viza commented Jul 11, 2017

Expanding on the note above, about injecting the interface... That is correct. You inject the interface instead of the concrete class, and gain full benefit of DI because injecting the interface protects your class from being coupled to any particular concrete class (or implementation). It does this because any concrete class that implements that interface can be used, and your class will function correctly and get what it needs, as long as the interface contract is fulfilled. As this example stands it's coupled to Guzzle. inject the interface and any replacement for Guzzle will JustWork with no modification to your code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment