使用带标签的服务

编辑本页

警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 2.3,现已不再维护。

本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

使用带标签的服务

标签是可以应用于任何服务的通用字符串(以及一些选项)。就其本身而言,标记实际上不会以任何方式改变服务的功能。但是如果您选择这样做,您可以向容器构建器请求使用特定标记标记的所有服务的列表。这在编译器传递中非常有用,您可以找到这些服务并以某种特定的方式使用或修改它们。

例如,如果你正在使用Swift Mailer,你可能会想象你想要实现一个“传输链”,这是一个实现类的集合\ Swift_Transport.使用链,你会希望Swift Mailer尝试多种方式传输消息,直到其中一种成功。

首先,定义TransportChain类:

12 3 4 5 6 7 8 9 10 11 12 13 14
TransportChain私人传输公共函数__construct()->传输=数组();}公共函数addTransport(\ Swift_Transport运输->传输[]=运输;}}

然后,将链定义为服务:

  • YAML
  • XML
  • PHP
1 2 3
服务:acme_mailer.transport_chain:类:TransportChain

使用自定义标记定义服务

现在你可能想要几个\ Swift_Transport类自动实例化并添加到链中addTransport ()方法。例如,您可以添加以下传输作为服务:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11
服务:acme_mailer.transport.smtp:类:\ Swift_SmtpTransport参数:-“% mailer_host %”标签:-名称:acme_mailer.transportacme_mailer.transport.sendmail:类:\ Swift_SendmailTransport标签:-名称:acme_mailer.transport

请注意,每个标记都被命名为acme_mailer.transport.这是将在编译器传递中使用的自定义标记。编译器传递使这个标记具有“意义”。

创建一个CompilerPass

你的编译器pass现在可以使用自定义标记向容器请求任何服务:

12 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
使用欧宝娱乐app下载地址组件DependencyInjectionContainerBuilder使用欧宝娱乐app下载地址组件DependencyInjection编译器CompilerPassInterface使用欧宝娱乐app下载地址组件DependencyInjection参考TransportCompilerPass实现了CompilerPassInterface公共函数过程(ContainerBuilder容器如果(!容器->有(“acme_mailer.transport_chain”)) {返回;}定义容器->findDefinition (“acme_mailer.transport_chain”);taggedServices容器->findTaggedServiceIds (“acme_mailer.transport”);foreachtaggedServices作为id= >标签){定义->addMethodCall (“addTransport”数组引用(id)));}}}

过程()方法检查是否存在acme_mailer.transport_chain服务,然后查找所有标记的服务acme_mailer.transport.它增加了acme_mailer.transport_chain服务调用addTransport ()对于每个“acme_mailer”。运输" service it has found. The first argument of each of these calls will be the mailer transport service itself.

将Pass注册到容器中

你还需要在容器中注册这个pass,它将在容器编译时运行:

1 2 3 4
使用欧宝娱乐app下载地址组件DependencyInjectionContainerBuilder容器ContainerBuilder ();容器->addCompilerPass (TransportCompilerPass ());

请注意

如果你使用的是全栈框架,编译器传递的注册方式是不同的。看到如何与编译器传递在捆绑欲知详情。

在标签上添加额外属性

有时,您需要关于使用标记标记的每个服务的附加信息。例如,您可能希望向传输链的每个成员添加别名。

首先,改变TransportChain类:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
TransportChain私人传输公共函数__construct()->传输=数组();}公共函数addTransport(\ Swift_Transport运输别名->传输(别名] =运输;}公共函数getTransport别名如果(array_key_exists (别名->传输)){返回->传输(别名];}}}

如你所见,当addTransport被称为,它需要的不仅仅是一个Swift_Transport对象,同时也是该传输的字符串别名。那么,如何允许每个带标记的传输服务也提供别名呢?

要回答这个问题,请更改服务声明:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11
服务:acme_mailer.transport.smtp:类:\ Swift_SmtpTransport参数:-“% mailer_host %”标签:-名称:acme_mailer.transport,别名:喷火acme_mailer.transport.sendmail:类:\ Swift_SendmailTransport标签:-名称:acme_mailer.transport,别名:酒吧

注意,您添加了一个泛型别名标签的键。要真正使用它,更新编译器:

12 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 28 29
使用欧宝娱乐app下载地址组件DependencyInjectionContainerBuilder使用欧宝娱乐app下载地址组件DependencyInjection编译器CompilerPassInterface使用欧宝娱乐app下载地址组件DependencyInjection参考TransportCompilerPass实现了CompilerPassInterface公共函数过程(ContainerBuilder容器如果(!容器->hasDefinition (“acme_mailer.transport_chain”)) {返回;}定义容器->getDefinition (“acme_mailer.transport_chain”);taggedServices容器->findTaggedServiceIds (“acme_mailer.transport”);foreachtaggedServices作为id= >标签){foreach标签作为属性){定义->addMethodCall (“addTransport”数组引用(id),属性“别名”)));} } } }

双循环可能会让人困惑。这是因为服务可以有多个标记。标记服务两次或两次以上acme_mailer.transport标签。第二个foreach循环遍历acme_mailer.transport为当前服务设置的标记,并为您提供属性。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。