Contributed by
Ryan Weaver
in #26658.

允许对控制器绑定标量值

当使用 service autowiring 时, _defaults.bind 选项允许 通过名称或类型来绑定参数。例如,你可以在程序中一次性定义 $projectDir 的值,每一个在构造器中使用了它的名字的服务都可以使用这个值:

1
2
3
4
5
# config/services.yaml
services:
    _defaults:
        bind:
            $projectDir: '%kernel.project_dir%'

但是,如果某些控制器的action中定义了 $projectDir 参数,那么这个配置就不会作用在它身上,参数将不被关联:

1
2
3
4
5
6
7
8
/**
 * @Route("/do-something")
 */
public function somethingAction($projectDir)
{
    // the $projectDir argument is not given the configured value
    // $projectDir 参数将不再被赋予配置好的值
}

在控制器里面,你需要使用 $this->getParameter('kernel.project_dir') 快捷方式或通过控制器的 __construct() 方法来传入该值。这一行为并不提供连续体验(服务的构造器绑定,其行为不同于控制器的action绑定),并且这是最为狂暴的 autowiring 自动关联方式。

这就是为何在 Symfony 4.1 你可以 绑定标量值到控制器参数。通常在 _defaults.bind 中定义绑定,然后把参数添加到控制器的 action 中(没有必要为它们定义构造器方法)。

Service decoration autowiring(服务装饰的自动关联)

Contributed by
Kévin Dunglas
in #25631.

Service decoration 允许你改变某个服务的行为,但不会影响到该服务原始版的其他使用。对服务进行装饰时,在配置信息中需要把被装饰的服务通过一种特殊的命名语法作为参数传进来:

1
2
3
4
5
6
7
8
9
10
11
12
13
# config/services.yaml
services:
    # this is the service you want to decorate
    # 这是你打算装修的服务
    App\Mailer: ~

    App\DecoratingMailer:
        decorates: App\Mailer
 
        # you must pass the original service as an argument, and its name
        # is: "decorating service ID" + ".inner"
        # 你必须把原始版服务作为参数传进来,其名称应为:"实施装修的 service ID" + ".inner"
        arguments: ['@App\DecoratingMailer.inner']

尽管是显式的,这种配置法看起来就像是 Symfony 的内部细节。这也是为何 Symfony 4.1 中 inner service 将在可能的情况下被自动关联。与前例相同的全新配置法是:

1
2
3
4
5
6
# config/services.yaml
services:
    App\Mailer: ~

    App\DecoratingMailer:
        decorates: App\Mailer

待装修服务的自动配置,将在满足以下条件时完成:

  1. The decorating service is autowired(实施装修的服务是自动关联的);
  2. The constructor of the decorating service has only one argument of the type of the decorated service.(实施装修的服务其构造器只能有 “待装修服务的类型(提示)” 这样一个参数)