Symfony框架的事件

当Symfony框架(或任何使用了HttpKernel的程序)在处理请求时,会有一些核心事件被派遣,以便你能够在处理进程内添加监听。这些事件被称为“kernel事件”。详细说明可以参考HttpKernel组件

Kernel Events 

每一个被kernel派遣的事件都是KernelEvent的子类。这意味着每个事件都可以访问到以下信息:

getRequestType()
返回请求(HttpKernelInterface::MASTER_REQUESTHttpKernelInterface::SUB_REQUEST) 的 type
getKernel()
返回用于处理请求的Kernel。
getRequest()
返回当前正被处理的 Request

kernel.request 

事件类: GetResponseEvent

本事件在Symfony中被极早派遣,于控制器被决定之前。

更多内容见 kernel.request事件

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
ProfilerListener 1024
TestSessionListener 192
SessionListener 128
RouterListener 32
LocaleListener 16
Firewall 8

kernel.controller 

事件类: FilterControllerEvent

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
 
public function onKernelController(FilterControllerEvent $event)
{
    $controller = $event->getController();
    // ...
 
    // the controller can be changed to any PHP callable
    // 控制器可以是任何PHP callable(回调)
    $event->setController($controller);
}

更多内容见 kernel.controller事件

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
RequestDataCollector 0

kernel.view 

事件类: GetResponseForControllerResultEvent

这个事件没有被FrameworkBundle使用,但它可以用于去实现一个view层子系统。本事件仅在控制器没有 返回Response对象时被调用。事件的作用,是允许其他一些返回值能够被转换成一个Response

控制器返回的值,可以通过getControllerResult方法访问到:

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\Response;
 
public function onKernelView(GetResponseForControllerResultEvent $event)
{
    $val = $event->getControllerResult();
    $response = new Response();
 
    // ... somehow customize the Response from the return value
    // ... 根据(控制器的)返回值,以某种方式定制一个响应对象
 
    $event->setResponse($response);
}

更多内容见 kernel.view事件

kernel.response 

事件类: FilterResponseEvent

本事件的用意,是让其他系统在Response对象创建之后能够修改或替换它。

1
2
3
4
5
6
public function onKernelResponse(FilterResponseEvent $event)
{
    $response = $event->getResponse();
 
    // ... modify the response object / 修改响应对象
}
ProfilerListener
收集当前请求的数据。
WebDebugToolbarListener
注入Web除错工具条。
ResponseListener
基于请求的格式来修复响应的 Content-Type
EsiListener
当响应需要为ESI标签而被解析时,添加一个 Surrogate-Control HTTP头。

更多内容见 kernel.response事件

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
EsiListener 0
ResponseListener 0
ResponseListener 0
ProfilerListener -100
TestSessionListener -128
WebDebugToolbarListener -128
StreamedResponseListener -1024

kernel.finish_request 

事件类: FinishRequestEvent

本事件的作用是,使你能够在子请求完成之后,重置程序中的“全局的、环境的”状态(global and environmental state)。例如,translator监听重置了translator的locale,使它和父请求中的一致。

1
2
3
4
5
6
7
8
9
10
public function onKernelFinishRequest(FinishRequestEvent $event)
{
    if (null === $parentRequest = $this->requestStack->getParentRequest()) {
        return;
    }
 
    // Reset the locale of the subrequest to the locale of the parent request
    // 重置子请求的locale为父请求的locale
    $this->setLocale($parentRequest);
}

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
LocaleListener 0
TranslatorListener 0
RouterListener 0
Firewall 0

kernel.terminate 

事件类: PostResponseEvent

本事件的作用,是在响应已经对客户端伺服完毕之后,执行一些任务。

更多内容见 kernel.terminate事件

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
EmailSenderListener 0

kernel.exception 

事件类: GetResponseForExceptionEvent

TwigBundle注册了一个 ExceptionListener 来把 Request 转发到一个由 exception_listener.controller 参数定义的给定控制器中去。

这个事件的监听,可以创建和设置一个Response对象,创建和设置一个新的Exception对象,或者什么也不做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
 
public function onKernelException(GetResponseForExceptionEvent $event)
{
    $exception = $event->getException();
    $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->setException($exception);
}

由于Symfony基于异常已经确保了响应被设置到一个最合适的状态码,直接对响应设置状态码则无法工作。如果你需要覆写状态码(不要毫无道理的这样做),设置x-Status-Code头:

1
2
3
4
5
6
7
8
$response = new Response(
    'Error',
    404, // this status code will be ignored / 这个状态码将被忽略
    array(
        'X-Status-Code' => 200 // this status code will actually be sent to the client
                               // 这个状态码将被真正发送到客户端
    )
);

更多内容见 kernel.response事件

以下是Symfony内置的注册到此事件的监听:

Listener Class Name / 监听器类名 Priority / 优先级
ProfilerListener 0
ExceptionListener -128

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)