【问题标题】:How to handle exceptions using events in Symfony 4?如何使用 Symfony 4 中的事件处理异常?
【发布时间】:2019-08-20 11:26:59
【问题描述】:

现在我正在尝试捕获这样的异常事件:

try {
    echo 1 / 0;
} catch (\Exception $e){
    $subs = new ExceptionSubscriber();
    $this->dispatcher->addSubscriber($subs);
};

我定义了 ExceptionSubscriber,如下所示:

class ExceptionSubscriber implements EventSubscriberInterface
{

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::EXCEPTION => [
                ['processException', 10],
                ['exception', -10],
            ],
        ];
    }

    public function exception(ExceptionEvent $event)
    {
        echo 'test321';
    }

    public function processException(ExceptionEvent $event)
    {
        echo 'test123';
    }
}

这是我的 services.yaml

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

我知道我捕获的常规 PHP 异常不是内核异常事件之一,在这种情况下我必须创建自定义异常事件,对吗?

我使用EventSubscriber而不是监听器来调度事件的方式很好

我必须调度这些事件还是以某种神奇的方式将它们传递给订阅者?

【问题讨论】:

  • 对不起,我刚刚坐下来,我已经受够了:P 是的,我看到了那些我仍然感到迷茫的问题,现在我正试图以某种方式导致内核异常,真的不知道如何只是还没有,但我在战斗 ;)
  • 我确实通过调用一个不存在的方法导致了一个致命错误,我正在考虑如何返回 symfony 标准 500 错误页面以外的其他内容
  • 好的,现在我明白了,对我来说,入口点是一个控制台,在将内核异常切换为控制台错误之后,现在它似乎可以工作了!

标签: php symfony exception symfony4


【解决方案1】:

Exception 被抛出(并且它未被处理)时,HttpKernel 捕获它并调度kernel.exception 事件。

但在您的示例中,这永远不会发生,因为您自己正在捕获异常。并试图在那里创建一个订阅者,这没有多大意义;如果有的话,你会分派一个事件。但是没有必要分派一个新事件,因为框架已经分派了kernel.exception 事件。

如果你想捕捉那个事件,你需要创建你自己的事件监听器。一个基本的例子:

class ExceptionListener
{
    public function onKernelException(ExceptionEvent $event)
    {
        $exception = $event->getException();

        // inspect the exception
        // do whatever else you want, logging, modify the response, etc, etc
    }
}

你需要配置这个类来真正监听这些事件:

services:
    App\EventListener\ExceptionListener:
        tags:
            - { name: kernel.event_listener, event: kernel.exception }

没有其他事情要做。任何未捕获的异常都会在这里处理。无需创建特定的 try/catch 块(尽管一般来说它们是个好主意,因为处理您自己的异常通常是一件好事)。

这在这些地方的文档中都有解释,其中包括:

【讨论】:

  • 订阅者胜于监听者:无需编写配置,直接在代码中订阅事件,...
  • 这主要是一个偏好问题。就个人而言,我更喜欢明确配置的侦听器,并且让侦听器只完成一项任务。
  • 我猜是的。我不应该这么严格。也许这篇文章可以改变你的想法:p tomasvotruba.cz/blog/2019/05/16/don-t-ever-use-listeners
  • 我已经熟悉那篇文章了。我碰巧不同意它提出的许多观点。
【解决方案2】:

控制器中未捕获的异常被 symfony 捕获,然后构造和调度内核异常事件。
实际上你没有捕捉到任何异常,你正在订阅一个事件。 Symfony 捕捉到它们,你会收到一个带有 getException 方法的事件。
您可以在这里找到更多信息:Symfony: How to Customize Error Pages

【讨论】:

  • 嗯好吧,所以我订阅了自动发送的事件,我在内核中通过添加$container->register('subscriber_service_id', ExceptionSubscriber::class) ->addTag('kernel.event_subscriber');
  • 我应该怎么做才能从服务中捕获异常?
  • @Maarduk Symfony 仍然是 php,要捕获异常只需使用常规的 try-catch 块,只有当 you 没有明确捕获异常时,symfony 才会捕获它然后发送事件。对于配置,它取决于您的环境。如果您正在使用框架包并启用了自动装配,Symfony 将自动获取任何实现EventSubscriberInterface 的服务并将其注册为订阅者。如果没有自动装配,您必须手动标记它。
猜你喜欢
  • 2019-12-16
  • 2011-02-01
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2011-10-13
  • 1970-01-01
  • 2019-09-06
相关资源
最近更新 更多