內建 Symfony 事件
Symfony 框架是一個 HTTP 請求-回應框架。在處理 HTTP 請求期間,框架(或任何使用HttpKernel 元件的應用程式)會分派一些事件,您可以使用這些事件來修改請求的處理方式以及回應的傳回方式。
Kernel 事件
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()
的標頭); - 如果以上兩者都不為 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