原文地址:https://www.drupal.org/node/2026959
服务容器具有多个优点,因为每个服务都可以通过一个字符串键来访问/实例化,并且拥有一个已定义的接口,它可以用其他实现来替换。如果需要修改一个已有的服务,只需要实现一个ServiceProviderBase的子类并且编写alter()方法。
如:在my_module中定义my_module/src/MyModuleServiceProvider.php
<?php /** * @file * Contains Drupal\my_module\MyModuleServiceProvider */ 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'); $definition->setClass('Drupal\language_test\LanguageTestManager'); } } ?>
需要注意,如果你想系统自动识别你对服务的修改,这个类的名称必须是你模块机读名称的驼峰版本,并且需要在模块的顶层命名空间下(Drupal\your_module_name),并且需要实现\Drupal\Core\DependencyInjection\ServiceModifierInterface (跟 ServiceProviderBase 一样)。
另一个可能比较实用的服务替换例子是字符串翻译(t()功能对应的服务)。Drupal核心没有提供区域语言或者非正式/正式语言,而它们可以提供最小的翻译差异。通过替换字符串翻译服务,可以很容易的在第三方模块中解决此问题。
最后,还可以通过定义register()方法来动态注册服务,虽然很少会这样做。