Symfony 5.4自定义错误控制器如何访问闪存消息或传递信息?
解决Symfony 5.4自定义错误控制器无法访问闪存消息的问题
问题原因
当你在控制器中抛出异常后,Symfony会启动一个子请求来调用自定义错误控制器。这个子请求会初始化全新的会话实例,导致无法直接获取父请求中设置的闪存消息。
解决方案一:自定义异常携带额外信息
既然闪存消息是用来传递额外提示,不如直接把信息封装到自定义异常中,跳过闪存的限制:
- 创建自定义异常类
// src/Exception/CustomBadRequestException.php namespace App\Exception; use Symfony\Component\HttpKernel\Exception\BadRequestException; class CustomBadRequestException extends BadRequestException { private $suggestion; public function __construct(string $message, string $suggestion, int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->suggestion = $suggestion; } public function getSuggestion(): string { return $this->suggestion; } }
- 在HomeController中抛出自定义异常
// HomeController中的代码 // 移除原闪存设置代码,直接用异常传递信息 throw new CustomBadRequestException("error.bad.request.accueil", 'This is a test');
- 在ErrorController中读取信息
public function show(\Throwable $exception, Request $request): Response { $suggestion = ''; if ($exception instanceof \App\Exception\CustomBadRequestException) { $suggestion = $exception->getSuggestion(); } return $this->render("commonoffice/error/test.html.twig", [ 'exception' => $exception, 'suggestion' => $suggestion ]); }
解决方案二:通过Kernel事件传递闪存消息
如果一定要用闪存机制,可以借助kernel.exception事件,在子请求启动前把闪存消息转移到可访问的位置:
- 创建事件订阅者
// src/EventSubscriber/ExceptionFlashTransferSubscriber.php namespace App\EventSubscriber; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ExceptionEvent; class ExceptionFlashTransferSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ ExceptionEvent::class => 'onKernelException', ]; } public function onKernelException(ExceptionEvent $event): void { $request = $event->getRequest(); $flashBag = $request->getSession()->getFlashBag(); // 将闪存消息转存到会话的普通属性(非一次性) if (!$flashBag->isEmpty()) { $request->getSession()->set('error_flash_data', $flashBag->all()); $flashBag->clear(); } } }
- 在ErrorController中读取转存的消息
public function show(\Throwable $exception, Request $request): Response { $flashMessages = $request->getSession()->get('error_flash_data', []); // 用完后删除避免后续请求重复显示 $request->getSession()->remove('error_flash_data'); return $this->render("commonoffice/error/test.html.twig", [ 'exception' => $exception, 'flash_messages' => $flashMessages ]); }
内容的提问来源于stack exchange,提问作者user19525065
相关产品推荐
相关产品推荐

