Skip to main content

Drupal Dependency Injection: Custom Services

Back-end Development
Drupal

I am writing a Drupal service class. What's the right way for me to get access to a service I want to use in my code?

You will need an entry in your module's services.yml file to define the service in the first place. Within that service definition, there is a section called arguments. This should be an array of all of the service names you wish to inject in your class. If the service is required for your class to function (as it usually is), it should be prefixed with an @ character.

For example:

services:
  services_examples.custom_service:
    class: Drupal\services_examples\ExampleService
    arguments: ['@date.formatter', '@datetime.time']

Within your class, you need to have a constructor method. The arguments of this constructor method need to correspond to each of the earlier service names, in that exact order.

To hold on to those services, you need to create protected variables in the class and assign the service objects to those variables within the constructor.

For example:

<?php

namespace Drupal\services_examples;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Datetime\DateFormatterInterface;

/**
 * A simple example of a service.
 */
class ExampleService implements ExampleServiceInterface {

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected DateFormatterInterface $dateFormatter;

  /**
   * The time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected TimeInterface $timeService;

  /**
   * Create a new ExampleService.
   */
  public function __construct(DateFormatterInterface $dateFormatter, TimeInterface $timeService) {
    $this->dateFormatter = $dateFormatter;
    $this->timeService = $timeService;
  }

}

That's it! You can now use the member variables to access the instance of the service that has been created for you by the dependency injection system.