跳到內容

內建 Symfony 事件

編輯此頁

Symfony 框架是一個 HTTP 請求-回應框架。在處理 HTTP 請求期間,框架(或任何使用HttpKernel 元件的應用程式)會分派一些事件,您可以使用這些事件來修改請求的處理方式以及回應的傳回方式。

Kernel 事件

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() 的標頭);
  • 如果以上兩者都不為 true,則會使用 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 授權條款授權。
目錄
    版本