Altering existing services, providing dynamic services

Last updated on
3 April 2017

There are several advantages of the service container. Since each service is accessed / instantiated using a single string key and has a defined interface, it can be swapped out with a different implementation. To modify existing services, implement a class extending ServiceProviderBase and the alter() method.

Note that if you want this service alteration to be recognized automatically, the name of this class is required to be a CamelCase version of your module's machine name followed by ServiceProvider, it is required to be in your module's top-level namespace Drupal\your_module_name, and it must implement \Drupal\Core\DependencyInjection\ServiceModifierInterface (which ServiceProviderBase does).

Note that while swapping services is very easy, you should use caution when making use of this feature. If multiple modules swap the same service, then neither module can predict if their swapped service will win eventually. If a service provides extension capabilities with events, hooks, or by other means, that is definitely more compatible with other extensions.

For example, define my_module/src/MyModuleServiceProvider.php for a module named my_module:

namespace Drupal\my_module;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;

 * Modifies the language manager service.
class MyModuleServiceProvider extends ServiceProviderBase {

   * {@inheritdoc}
  public function alter(ContainerBuilder $container) {
    // Overrides language_manager class to test domain language negotiation.
    $definition = $container->getDefinition('language_manager');

Other examples of where service swapping may be useful is to swap out the string translation service (the one behind t()). A common feature request that Drupal core does not provide is to have regional language variants or informal/formal languages, where the translation differences may be minimal. By swapping the string translation service, this is easy to resolve in a contributed module.

Finally, it is also possible to define the register() method to register services dynamically, however this should be very rare.