内置 Symfony 事件
Symfony 框架是一个 HTTP 请求-响应框架。在处理 HTTP 请求期间,框架(或任何使用 HttpKernel 组件 的应用程序)会分发一些 事件,你可以使用这些事件来修改请求的处理方式以及响应的返回方式。
内核事件
HttpKernel 组件分发的每个事件都是 KernelEvent 的子类,它提供以下信息
- getRequestType()
- 返回请求的类型 (
HttpKernelInterface::MAIN_REQUEST
或HttpKernelInterface::SUB_REQUEST
)。 - getKernel()
- 返回处理请求的 Kernel。
- getRequest()
- 返回当前正在处理的
Request
。 - isMainRequest()
- 检查这是否是主请求。
kernel.request
事件类: RequestEvent
此事件在 Symfony 中非常早期被分发,在控制器被确定之前。它对于向 Request 添加信息或提前返回 Response 以停止请求的处理非常有用。
另请参阅
阅读更多关于 kernel.request 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.request
kernel.controller
事件类: ControllerEvent
此事件在控制器被解析之后但在执行之前被分发。它对于初始化控制器稍后需要的东西非常有用,例如 值解析器,甚至完全更改控制器
1 2 3 4 5 6 7 8 9
use Symfony\Component\HttpKernel\Event\ControllerEvent;
public function onKernelController(ControllerEvent $event): void
{
// ...
// the controller can be changed to any PHP callable
$event->setController($myCustomController);
}
另请参阅
阅读更多关于 kernel.controller 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.controller
kernel.controller_arguments
此事件在控制器被调用之前分发。它对于配置将要传递给控制器的参数非常有用。通常,这用于将 URL 路由参数映射到其对应的命名参数;或者在找到 Request
类型提示时传递当前请求
1 2 3 4 5 6 7 8 9 10 11 12 13
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
public function onKernelControllerArguments(ControllerArgumentsEvent $event): void
{
// ...
// get controller and request arguments
$namedArguments = $event->getRequest()->attributes->all();
$controllerArguments = $event->getArguments();
// set the controller arguments to modify the original arguments or add new ones
$event->setArguments($newArguments);
}
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.controller_arguments
kernel.view
事件类: ViewEvent
此事件在控制器执行之后但仅当控制器没有返回 Response 对象时分发。它对于将返回的值(例如,包含一些 HTML 内容的字符串)转换为 Symfony 所需的 Response
对象非常有用
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ViewEvent;
public function onKernelView(ViewEvent $event): void
{
$value = $event->getControllerResult();
$response = new Response();
// ... somehow customize the Response from the return value
$event->setResponse($response);
}
另请参阅
阅读更多关于 kernel.view 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.view
kernel.response
事件类: ResponseEvent
此事件在控制器或任何 kernel.view
监听器返回 Response
对象后分发。它对于在发送响应之前修改或替换响应非常有用(例如,添加/修改 HTTP 标头,添加 cookie 等)
1 2 3 4 5 6 7 8
use Symfony\Component\HttpKernel\Event\ResponseEvent;
public function onKernelResponse(ResponseEvent $event): void
{
$response = $event->getResponse();
// ... modify the response object
}
另请参阅
阅读更多关于 kernel.response 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.response
kernel.finish_request
事件类: FinishRequestEvent
此事件在 kernel.response
事件之后分发。它对于重置应用程序的全局状态非常有用(例如,翻译器监听器将翻译器的语言环境重置为父请求的语言环境)
1 2 3 4 5 6 7 8 9 10 11
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
public function onKernelFinishRequest(FinishRequestEvent $event): void
{
if (null === $parentRequest = $this->requestStack->getParentRequest()) {
return;
}
// reset the locale of the subrequest to the locale of the parent request
$this->setLocale($parentRequest);
}
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.finish_request
kernel.terminate
事件类: TerminateEvent
此事件在响应已发送之后(在执行 handle() 方法之后)分发。它对于执行不需要完成即可发送响应的缓慢或复杂任务非常有用(例如,发送电子邮件)。
另请参阅
阅读更多关于 kernel.terminate 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.terminate
kernel.exception
事件类: ExceptionEvent
此事件在处理 HTTP 请求期间发生错误时立即分发。它对于从错误中恢复或修改作为响应发送的异常详细信息非常有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
public function onKernelException(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
$response = new Response();
// setup the Response object based on the caught exception
$event->setResponse($response);
// you can alternatively set a new Exception
// $exception = new \Exception('Some special exception');
// $event->setThrowable($exception);
}
注意
TwigBundle 注册了一个 ErrorListener,它将 Request
转发到由 exception_listener.controller
参数定义的给定控制器。
Symfony 使用以下逻辑来确定响应的 HTTP 状态代码
- 如果 isClientError(),isServerError() 或 isRedirect() 为 true,则使用你的
Response
对象上的状态代码; - 如果原始异常实现了 HttpExceptionInterface,则调用异常上的
getStatusCode()
并使用(来自getHeaders()
的标头也会被添加); - 如果以上两者都不为真,则使用 500 状态代码。
注意
如果你想覆盖异常响应的状态代码,如果没有充分的理由,你不应该这样做,首先调用 ExceptionEvent::allowCustomResponseCode()
,然后在响应上设置状态代码
1 2 3
$event->allowCustomResponseCode();
$response = new Response('No Content', 204);
$event->setResponse($response);
在上面的示例中发送到客户端的状态代码将是 204
。如果省略 $event->allowCustomResponseCode()
,则内核将根据抛出的异常类型设置适当的状态代码。
另请参阅
阅读更多关于 kernel.exception 事件 的信息。
执行此命令以找出为此事件注册了哪些监听器及其优先级
1
$ php bin/console debug:event-dispatcher kernel.exception