跳到内容

内置 Symfony 事件

编辑此页

Symfony 框架是一个 HTTP 请求-响应框架。在处理 HTTP 请求期间,框架(或任何使用 HttpKernel 组件 的应用程序)会分发一些 事件,你可以使用这些事件来修改请求的处理方式以及响应的返回方式。

内核事件

HttpKernel 组件分发的每个事件都是 KernelEvent 的子类,它提供以下信息

getRequestType()
返回请求的类型 (HttpKernelInterface::MAIN_REQUESTHttpKernelInterface::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

事件类: ControllerArgumentsEvent

此事件在控制器被调用之前分发。它对于配置将要传递给控制器的参数非常有用。通常,这用于将 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
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。
目录
    版本