首页 > 解决方案 > Symfony 异常订阅者未触发

问题描述

我需要格式化错误消息并以 JSON 格式输出。

我有以下事件订阅者:


namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;

final class ExceptionSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::EXCEPTION => 'onKernelException'];
    }

    public function onKernelException(ExceptionEvent $event) {/*..*/}
}

并在以下配置./config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\EventSubscriber\ExceptionSubscriber:
        tags:
            - {name: kernel.event_subscriber, event: kernel.exception}

当控制器抛出错误时,此事件订阅者正在工作。

但是如果我有其他错误,例如错误的 DI 注入

class FooBar {
    public __constructor(NonExistingService $service) {/*..*/}
}

那么输出仍然是 Html 格式和 Symfony 错误页面。


如何通过我的类将 Symfony 捕获的任何错误转换为 JSON?

标签: phpsymfonysymfony5

解决方案


我发现这里有什么问题。

问题是,如果您有例如配置错误,您的事件将尚未连接。

在我的代码中,我有这个:

// index.php

if ($_SERVER['APP_DEBUG']) {
    umask(0000);

    $errorHandler = Debug::enable();
}

$kernel = new Kernel();
/* .. */

Debug::enable()实际上设置了错误处理程序(没有启动时只有 PHP 默认错误处理程序)。

我已经扩展Debug了自己的课程:


namespace App\Error;

use Symfony\Component\ErrorHandler\BufferingLogger;
use Symfony\Component\ErrorHandler\Debug as SymfonyDebug;
use Symfony\Component\ErrorHandler\ErrorHandler;

class Debug extends SymfonyDebug
{
    public static function enable(): ErrorHandler
    {
        if ($_SERVER['APP_DEBUG']) {
            umask(0000);

            $errorHandler = parent::enable();
        }

        return self::setDefaultErrorHandler($errorHandler ?? null);
    }

    private static function setDefaultErrorHandler(?ErrorHandler $errorHandler): ErrorHandler
    {
        $errorHandler ??= ErrorHandler::register(new ErrorHandler(new BufferingLogger(), true));

        $errorHandler->setExceptionHandler([ExceptionHandler::class, 'renderException']);

        return $errorHandler;
    }
}


现在所有错误都通过我App\Error\ExceptionHandler可以输出的地方JsonResponse


推荐阅读