捆绑特定的异常监听器

时间:2019-02-18 14:08:49

标签: php symfony oop symfony4

让我们说我有3个不同的捆绑包。

我正在将事件监听器添加到每个捆绑包中。如果Bundle1中有任何异常,则Bundle2和Bundle3不应监听它。

我已经将其添加到每个bundle eventlistener中进行了测试,但是当Bundle2中出现任何错误时,Bundle1也会监听并尝试处理它。

如何处理这种情况?

如果需要任何代码,那么这是我的service.yaml包:

kernel.listener.test1bundle.exceptionlistener:
    class: App\test1bundle\EventListener\ExceptionListener
    tags:
        - { name: kernel.event_listener, event: kernel.exception}

这是我的异常侦听器:

public function onKernelException(GetResponseForExceptionEvent $event)
{
    // You get the exception object from the received event
    $exception = $event->getException();
    $message = [ 
        "errors" => [
            [
                "title" => "Internal error in test1 bundle",
                "detail" => $exception->getMessage()
            ]
        ]
    ];

    $response = new JsonResponse();
    $response->setData($message);

    $response->headers->set('Content-Type', 'application/problem+json');

    $event->setResponse($response);
}

我读到有可能只是监听控制器。但是在那种情况下,控制器侦听器也会侦听异常吗?

2 个答案:

答案 0 :(得分:3)

您需要做的是创建不同的异常“族”,每个事件侦听器都应根据其亲缘关系决定对异常采取行动还是不采取行动。

例如可以说,在每个捆绑包上都创建了一个抽象异常:

abstract class BundleOneException extends \Exception {}

(与BundleTwo和BundleThree相同)。现在,在每个捆绑包上,您引发的每个异常都应该是从该异常扩展而来的。

然后在每个侦听器上可以做:

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $exception = $event->getException();

    if (!$exception instanceof BundleOneException) {
        return;
    }

    // otherwise, do your thing

}

所有侦听器都在侦听所有异常,但是它们只会对适当的异常起作用。

这是处理情况的最实用方法。是的,您需要每个捆绑软件在其引发的异常类型上保持一致;但是抛出通用异常并不是一个好习惯(这种情况已证明了这一点)。

答案 1 :(得分:1)

事件监听器总线为应用程序中的所有捆绑软件共享,因为所有捆绑软件都是为特定的AppKernel实例化的。您在这里有几种选择:

  1. 让不同的内核处理应用程序的不同部分(这意味着您必须在public/index.php前端控制器中将请求路由到它们),并在其中添加单独的侦听器作为服务。但是,这可能非常麻烦,因为通常您不仅要处理一个应用程序,还要处理多个应用程序。

  2. 如果您知道要在侦听器中捕获的特定异常,则可以将每个捆绑中的异常归为子类,并且只有在类{{3}匹配的情况下,才在ExceptionListener s中继续处理}。

  3. 您还可以获取异常堆栈跟踪,并使用as @yivi suggested in this answer进行内省,并进行一些反复的挖掘,以查看监听器中捕获的异常是否确实被抛出到特定文件中,也许是通过查看此处的file字段。

但是总的来说,对于我来说,需要这样的事情看起来像是应用程序代码中关注点分离原则的问题。看来您将捆绑包视为单独的应用程序,但是据我所知,这并不是用于捆绑包的分解方式。 Symfony的最佳做法现在建议仅使用AppBundle,但是即使您想添加更多的包,这样做的原因仍然是按域划分代码,这将自动导致每个捆绑。