跳到内容

如何使用服务定义对象

编辑此页

服务定义是描述容器应如何构建服务的指令。它们不是您的应用程序使用的实际服务。 容器将根据定义中的配置创建实际的类实例。

通常,您会使用 YAML、XML 或 PHP 来描述服务定义。 但是,如果您正在使用服务容器执行高级操作,例如使用 Compiler Pass 或创建 Dependency Injection Extension,您可能需要直接使用 Definition 对象,这些对象定义了如何实例化服务。

获取和设置服务定义

有一些有用的方法可以用来处理服务定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\DependencyInjection\Definition;

// finds out if there is an "app.mailer" definition
$container->hasDefinition('app.mailer');
// finds out if there is an "app.mailer" definition or alias
$container->has('app.mailer');

// gets the "app.user_config_manager" definition
$definition = $container->getDefinition('app.user_config_manager');
// gets the definition with the "app.user_config_manager" ID or alias
$definition = $container->findDefinition('app.user_config_manager');

// adds a new "app.number_generator" definition
$definition = new Definition(\App\NumberGenerator::class);
$container->setDefinition('app.number_generator', $definition);

// shortcut for the previous method
$container->register('app.number_generator', \App\NumberGenerator::class);

使用定义

创建新定义

除了操作和检索现有定义之外,您还可以使用 Definition 类定义新的服务定义。

Definition 类的第一个可选参数是当从容器中获取服务时返回的对象的完全限定类名

1
2
3
4
5
6
7
8
9
10
11
use App\Config\CustomConfigManager;
use App\Config\UserConfigManager;
use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition(UserConfigManager::class);

// override the class
$definition->setClass(CustomConfigManager::class);

// get the class configured for this definition
$class = $definition->getClass();

构造函数参数

Definition 类的第二个可选参数是一个数组,其中包含传递给从容器中获取服务时返回的对象的构造函数的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use App\Config\DoctrineConfigManager;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

$definition = new Definition(DoctrineConfigManager::class, [
    new Reference('doctrine'), // a reference to another service
    '%app.config_table_name%',  // will be resolved to the value of a container parameter
]);

// gets all arguments configured for this definition
$constructorArguments = $definition->getArguments();

// gets a specific argument
$firstArgument = $definition->getArgument(0);

// adds a new named argument
// '$argumentName' = the name of the argument in the constructor, including the '$' symbol
$definition = $definition->setArgument('$argumentName', $argumentValue);

// adds a new argument
$definition->addArgument($argumentValue);

// replaces argument on a specific index (0 = first argument)
$definition->replaceArgument($index, $argument);

// replaces all previously configured arguments with the passed array
$definition->setArguments($arguments);

警告

不要使用 get() 来获取您想要作为构造函数参数注入的服务,因为该服务尚不可用。 相反,请使用如上所示的 Reference 实例。

方法调用

如果您正在使用的服务使用 setter 注入,那么您也可以在定义中操作任何方法调用

1
2
3
4
5
6
7
8
9
10
11
// gets all configured method calls
$methodCalls = $definition->getMethodCalls();

// configures a new method call
$definition->addMethodCall('setLogger', [new Reference('logger')]);

// configures an immutable-setter
$definition->addMethodCall('withLogger', [new Reference('logger')], true);

// replaces all previously configured method calls with the passed array
$definition->setMethodCalls($methodCalls);

提示

在服务容器文章的 PHP 代码块中,有更多关于使用定义的具体方法的示例,例如 使用工厂创建服务如何使用父服务管理通用依赖项.

注意

此处更改服务定义的方法只能在容器编译之前使用。 容器一旦编译,您就无法进一步操作服务定义。 要了解有关编译容器的更多信息,请参阅 编译容器

引入文件

在某些用例中,您可能需要在服务本身加载之前包含另一个文件。 为此,您可以使用 setFile() 方法

1
$definition->setFile('/src/path/to/file/foo.php');

请注意,Symfony 将在内部调用 PHP 语句 require_once,这意味着您的文件在每个请求中只会被包含一次。

这项工作,包括代码示例,均根据 Creative Commons BY-SA 3.0 许可获得许可。
目录
    版本