跳转到主要内容
yplam 提交于 24 September 2014

原文地址: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()方法来动态注册服务,虽然很少会这样做。