Overview of the Dependency Injection Container and Services.
The Services and Dependency Injection Container concepts have been adopted by Drupal from the Symfony framework. A "service" (such as accessing the database, sending email, or translating user interface text) is defined (given a name and an interface or at least a class that defines the methods that may be called), and a default class is designated to provide the service. These two steps must be done together, and can be done by Drupal Core or a module. Other modules can then define alternative classes to provide the same services, overriding the default classes. Classes and functions that need to use the service should always instantiate the class via the dependency injection container (also known simply as the "container"), rather than instantiating a particular service provider class directly, so that they get the correct class (default or overridden).
See https://www.drupal.org/node/2133171 for more detailed information on services and the dependency injection container.
Drupal core defines many core services in the core.services.yml file (in the top-level core directory). Some Drupal Core modules and contributed modules also define services in modulename.services.yml files. API reference sites (such as https://api.drupal.org) generate lists of all existing services from these files. Look for the Services link in the API Navigation block. Alternatively you can look through the individual files manually.
A typical service definition in a *.services.yml file looks like this:
path.alias_manager: class: Drupal\Core\Path\AliasManager arguments: ['@path.crud', '@path.alias_whitelist', '@language_manager']
Some services use other services as factories; a typical service definition is:
cache.entity: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get arguments: [entity]
The first line of a service definition gives the unique machine name of the service. This is often prefixed by the module name if provided by a module; however, by convention some service names are prefixed by a group name instead, such as cache.* for cache bins and plugin.manager.* for plugin managers.
The class line either gives the default class that provides the service, or if the service uses a factory class, the interface for the service. If the class depends on other services, the arguments line lists the machine names of the dependencies (preceded by '@'); objects for each of these services are instantiated from the container and passed to the class constructor when the service class is instantiated. Other arguments can also be passed in; see the section at https://www.drupal.org/node/2133171 for more detailed information.
Services using factories can be defined as shown in the above example, if the factory is itself a service. The factory can also be a class; details of how to use service factories can be found in the section at https://www.drupal.org/node/2133171.
As noted above, if you need to use a service in your code, you should always instantiate the service class via a call to the container, using the machine name of the service, so that the default class can be overridden. There are several ways to make sure this happens:
// Retrieve the entity.manager service object (special method exists). $manager = \Drupal::entityManager(); // Retrieve the service object for machine name 'foo.bar'. $foobar = \Drupal::service('foo.bar');
As a note, you should always use dependency injection (via service arguments or create()/createInstance() methods) if possible to instantiate services, rather than service location (via the \Drupal class), because:
If your module needs to define a new service, here are the steps:
Services can also be defined dynamically, as in the \Drupal\Core\CoreServiceProvider class, but this is less common for modules.
Some services have tags, which are defined in the service definition. See Service Tags for usage.
Modules can override the default classes used for services. Here are the steps:
public function alter(ContainerBuilder $container) { // Override the language_manager class with a new class. $definition = $container->getDefinition('language_manager'); $definition->setClass('Drupal\my_module\MyLanguageManager'); }
Note that $container here is an instance of \Drupal\Core\DependencyInjection\ContainerBuilder.
https://www.drupal.org/node/2133171
\Symfony\Component\DependencyInjection\ContainerInterface
Name | Location | Description |
---|---|---|
Container | core/lib/Drupal/Component/DependencyInjection/Container.php | Provides a container optimized for Drupal's needs. |
ContainerBuilder | core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php | Drupal's dependency injection container builder. |
CoreServiceProvider | core/lib/Drupal/Core/CoreServiceProvider.php | ServiceProvider class for mandatory core services. |
PhpArrayContainer | core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php | Provides a container optimized for Drupal's needs. |
ServiceProviderBase | core/lib/Drupal/Core/DependencyInjection/ServiceProviderBase.php | Base service provider implementation. |
Name | Location | Description |
---|---|---|
ServiceModifierInterface | core/lib/Drupal/Core/DependencyInjection/ServiceModifierInterface.php | Interface that service providers can implement to modify services. |
ServiceProviderInterface | core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php | Interface that all service providers must implement. |
© 2001–2016 by the original authors
Licensed under the GNU General Public License, version 2 and later.
Drupal is a registered trademark of Dries Buytaert.
https://api.drupal.org/api/drupal/core!core.api.php/group/container/8.1.x