Structure of a service file

Last updated on
2 February 2024

This documentation needs review. See "Help improve this page" in the sidebar.

Services are defined in a file called 'example.services.yml', assuming that your module is named 'example.' This file should be located in the root directory of your module project. Drupal automatically detects and utilizes these defined services.

Example of a example.services.yml file:

services:

  # Defines a simple service which requires no parameter for its constructor.
  example.simple:
    class: Drupal\example\Simple

  # Defines a service which requires the module_handler for its constructor.
  example.with_module_handler:
    class: Drupal\example\WithModuleHandler
    arguments: ['@module_handler', '%example.parameter%']

parameters:
  example.parameter: TRUE

In Drupal service configuration, it's important to note that the 'arguments' key often contains elements that start with '@' and '%'.

  1. The '@' symbol is used to inject other services, like '@module_handler,' which seamlessly integrates the 'module_handler' service into the current service.
  2. On the other hand, the '%' symbol signifies the use of parameters, as seen in '%example.parameter%,' which holds predefined values and enhances the flexibility of configuration settings. Understanding the distinction between these symbols is crucial for effective Drupal service configuration.

More examples can be found in core.services.yml or any module's service file. All definitions are aggregated and saved as a serialized array in the database.

Properties of a service

Note for Drupal > 8

Links in this section lead to Symfony documentation specific to its version used in Drupal 8. Please use version switcher on the Symfony site to see information relevant to your Drupal version.

  • abstract: The service definition will not result in an actual service. The service is supposed to be used as 'parent'. Values: ‘true’ = service will be abstract; ‘false’ (default) = service will be instantiated.
  • alias: Alias name for a service. More information.
  • arguments: Argument(s) to be used with the factory method (in case of ‘factory_class’) or with the class constructor (in case of ‘class’). A '@' indicates another service, and then what is put in here is the name of the service, as defined in its services.yml file. An argument wrapped in '%' characters represents a parameter, which can be defined in the 'parameters' section of the file. A '@?' indicates that the dependency is optional (more info). More information, & More on parameters
  • calls: Used for setter injection. Defines additional methods to call after the service has been instantiated. More information.
  • class: The class of the service.
  • configurator: A callable which configures a service after its instantiation. More information.
  • decorates: A service definition that will be replaced/overridden by this service definition. Can be combined with 'parent' to more easily replace the original service definition. More information.
  • factory: The class (and factory_method) that will instantiate the service class. More information.
  • file: A file which is included just before the service gets loaded. More information.
  • parent: A service definition which properties will be inherited. See 'abstract'. More information.
  • properties: More information.
  • public: Set the service as public or private. Private services can only be used as argument for other services. More information.
    ‘true’ (default): service is public. ‘false’: service is private.
  • shared: Determines if a service is reused by the container. ‘true’ (default): always return the same instance; the service acts as a singleton. ‘false’: create a new instance every time the service is called. More information.
  • synchronized: The service will be reconfigured on each scope change (deprecated starting from Symfony 2.7) More information.
  • synthetic: The service is injected into the container instead of being created by the container. Values: ‘true’ = synthetic service; ‘false’ (default) = normal service. More information.
  • tags: A name to identify groups of services. Tags are used in compiler passes and for collecting cache bins. More information.

More examples of services.yml:

Let's say you're developing a module called 'icecream' and you require the injection of a database service. To achieve this, your 'icecream.services.yml' file should include the following setup:

services:
  icecream.scoop:
    class: Drupal\icecream\Services\Scoopdb
    arguments: ['@database'] 

Where...

  • icecream.scoop is our service name.
    Following best practices, we have named our service 'icecream.scoop' by prefixing it with the module name, which is considered a widely recommended convention.
  • The 'class' key specifies the specific class that the service represents. In this case, it points to the
    Drupal\icecream\Services\Scoopdb class.
  •  Arguments contains the names of the services that need to be injected inside our custom service. 
    '@database' is in our case.

The class points to a file called Scoopdb.php inside the src/Services folder.

Our Scoopdb.php file would contain:

<?php

namespace Drupal\icecream\Services;

use Drupal\Core\Database\Connection;

/**
 * Class Scoopdb.
 */
class Scoopdb {

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected Connection $database;

  /**
   * Constructs a new Scoopdb object.
   *
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection.
   */
  public function __construct(Connection $connection) {
    $this->database = $connection;
  }

  /**
   * Returns list of nids from icecream table.
   */
  public function icecream() {
    $query = $this->database->query('SELECT nid FROM {icecream}');
    $result = $query->fetchAssoc();
    return $result;
  }

}

In your .module or .install files, you can access your service using \Drupal::service('icecream.scoop'). If you want to use this service inside another service, make sure to include it as a dependency by adding it to the constructor of the other service. This way, you can easily use one service within another.

Help improve this page

Page status: Needs review

You can: