事件和事件监听器

编辑本页

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

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

事件和事件监听器

在Symfony应用程序执行期间,会触发大量事件通知欧宝娱乐app下载地址。您的应用程序可以侦听这些通知,并通过执行任何一段代码来响应它们。

欧宝娱乐app下载地址Symfony触发了几个与内核相关的事件在处理HTTP请求时。第三方捆绑包也可以分派事件,你甚至可以分派自定义事件从你自己的代码。

本文中显示的所有示例都使用相同的方法KernelEvents:异常事件以保持一致性。在您自己的应用程序中,您可以使用任何事件,甚至在同一个订阅者中混合使用多个事件。

创建事件监听器

监听事件最常见的方法是注册事件监听器

12 34 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 30 31 32 33 34 35 36
/ / src / EventListener / ExceptionListener.php名称空间应用程序EventListener使用欧宝娱乐app下载地址组件HttpFoundation响应使用欧宝娱乐app下载地址组件HttpKernel事件ExceptionEvent使用欧宝娱乐app下载地址组件HttpKernel异常HttpExceptionInterfaceExceptionListener公共函数onKernelException(ExceptionEvent事件//从接收到的事件中获取异常对象异常事件->getThrowable ();消息= sprintf ('我的错误显示:%s,代码:%s'异常->getMessage (),异常->getCode ());//自定义响应对象以显示异常详细信息响应反应();响应->setContent (消息);// HttpExceptionInterface是一个特殊类型的异常//保存状态码和头信息如果异常运算符HttpExceptionInterface) {响应->setStatusCode (异常->getStatusCode ());响应->->替换(异常->getHeaders ());}其他的响应->setStatusCode(响应::HTTP_INTERNAL_SERVER_ERROR);}//向事件发送修改后的响应对象事件->setResponse (响应);}}

提示

每个事件接收的类型略有不同美元的事件对象。为kernel.exception事件,它是ExceptionEvent.请查看欧宝娱乐app下载地址Symfony事件引用查看每个事件提供的对象类型。

创建了类之后,您需要将其注册为服务,并通知Symfony它是欧宝娱乐app下载地址kernel.exception事件,使用一个特殊的“标签”:

  • YAML
  • XML
  • PHP
1 2 3 4 5
#配置/ services.yaml服务:App \ EventListener \ ExceptionListener:标签:-名称:kernel.event_listener,事件:kernel.exception

欧宝娱乐app下载地址Symfony遵循这个逻辑来决定在事件监听器类中调用哪个方法:

  1. 如果kernel.event_listener标记定义方法属性,这是要调用的方法的名称;
  2. 如果没有方法属性定义时,请尝试调用名称为的方法+“驼峰式事件名称”(例如:onKernelException ()方法。kernel.exception事件);
  3. 方法也没有定义该方法,请尝试调用__invoke ()Magic方法(使事件侦听器可调用);
  4. 如果__invoke ()方法也未定义,则抛出异常。

请注意

属性的可选属性kernel.event_listener标签被称为优先级,默认为正整数或负整数0它还控制侦听器执行的顺序(数字越高,侦听器执行得越早)。当您需要保证一个侦听器在另一个侦听器之前执行时,这很有用。内部Symfony侦听器的优先级通常从欧宝娱乐app下载地址-256年256但是您自己的侦听器可以使用任何正整数或负整数。

创建事件订阅服务器

监听事件的另一种方法是通过事件订阅者,这是一个定义了一个或多个侦听一个或多个事件的方法的类。与事件侦听器的主要区别是订阅者总是知道它们正在侦听哪些事件。

如果不同的事件订阅器方法侦听相同的事件,则它们的顺序由优先级参数。此值为正整数或负整数,默认为0.数值越高,方法就越早被调用。优先级为所有侦听器和订阅者聚合,因此可以在其他侦听器和订阅者中定义的方法之前或之后调用您的方法。要了解有关事件订阅者的更多信息,请阅读EventDispatcher组件

下面的示例显示了一个事件订阅器,它定义了几个侦听相同事件的方法kernel.exception事件:

12 34 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 30 31 32 33 34 35 36
/ / src / EventSubscriber / ExceptionSubscriber.php名称空间应用程序EventSubscriber使用欧宝娱乐app下载地址组件EventDispatcherEventSubscriberInterface使用欧宝娱乐app下载地址组件HttpKernel事件ExceptionEvent使用欧宝娱乐app下载地址组件HttpKernelKernelEventsExceptionSubscriber实现了EventSubscriberInterface公共静态函数getSubscribedEvents()//返回订阅的事件及其方法和优先级返回[KernelEvents::异常=> [[“processException”10]、[“logException”0]、[“notifyException”-10],],];}公共函数processException(ExceptionEvent事件/ /……公共函数logException(ExceptionEvent事件/ /……公共函数notifyException(ExceptionEvent事件/ /……}}

就是这样!你的services.yaml文件应已设置,以便从EventSubscriber目录中。欧宝娱乐app下载地址Symfony负责其余的工作。

提示

如果你的方法是在抛出异常时调用,请仔细检查是否加载服务EventSubscriber目录和有可以使用autoconfigure启用。也可以手动添加kernel.event_subscriber标签。

请求事件,检查类型

一个页面可以发出几个请求(一个主请求,然后多个子请求——通常是在在模板中嵌入控制器).对于核心Symfony事件欧宝娱乐app下载地址,你可能需要检查事件是“主”请求还是“子请求”:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src / EventListener / RequestListener.php名称空间应用程序EventListener使用欧宝娱乐app下载地址组件HttpKernel事件RequestEventRequestListener公共函数onKernelRequestRequestEvent (事件如果(!事件->isMasterRequest ()) {//如果不是主请求就不做任何事情返回;}/ /……}}

有些事情,比如查看信息真正的请求时,可能不需要对子请求监听器进行处理。

监听器或订阅器

侦听器和订阅者可以在同一个应用程序中使用。使用它们中的任何一种通常是个人喜好的问题。然而,它们都有一些小优点:

  • 订阅者更容易重用因为事件的知识保存在类中,而不是服务定义中。这就是Symfony内部使用订阅者的原因;欧宝娱乐app下载地址
  • 听众更灵活因为bundle可以根据某些配置值有条件地启用或禁用它们。

事件的别名

当通过依赖注入配置事件监听器和订阅器时,Symfony的核心事件也可以通过相应事件类的全限定类名(FQCN)引用:欧宝娱乐app下载地址

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ / src / EventSubscriber / RequestSubscriber.php名称空间应用程序EventSubscriber使用欧宝娱乐app下载地址组件EventDispatcherEventSubscriberInterface使用欧宝娱乐app下载地址组件HttpKernel事件RequestEventRequestSubscriber实现了EventSubscriberInterface公共静态函数getSubscribedEvents()数组返回RequestEvent [::类= >“onKernelRequest”,);}公共函数onKernelRequestRequestEvent (事件/ /……}}

在内部,事件FQCN被视为原始事件名称的别名。由于在编译服务容器时已经发生了映射,因此在检查事件分配器时,使用FQCN而不是事件名称的事件侦听器和订阅者将出现在原始事件名称下。

通过注册编译器通道,可以为自定义事件扩展别名映射AddEventAliasesPass

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src / Kernel.php名称空间应用程序使用应用程序事件MyCustomEvent使用欧宝娱乐app下载地址组件DependencyInjectionContainerBuilder使用欧宝娱乐app下载地址组件EventDispatcherDependencyInjectionAddEventAliasesPass使用欧宝娱乐app下载地址组件HttpKernel内核作为BaseKernel内核扩展BaseKernel受保护的函数构建(ContainerBuilder容器容器->addCompilerPass (AddEventAliasesPass ([MyCustomEvent::类= >“my_custom_event”)));}}

编译器传递将始终扩展现有别名列表。因此,使用不同的配置注册多个传递实例是安全的。

调试事件监听器

您可以使用控制台找出在事件调度程序中注册了哪些侦听器。要显示所有事件及其监听器,运行:

1
PHP bin/控制台调试:event-dispatcher

你可以通过指定某个事件的名称来获取它的注册监听器:

1
PHP bin/控制台调试:event-dispatcher kernel.exception
此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。