捆绑特定的异常侦听器

Bundle specific exception listener

假设我有 3 个不同的捆绑包。

我正在为每个包添加事件侦听器。当Bundle1有异常时,Bundle2和Bundle3不应该监听。

我已经测试了它添加到每个 bundle 事件监听器,但是当 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);
}

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

您需要做的是创建不同的 "families" 异常,每个事件侦听器应根据其出身决定对异常采取行动或不采取行动。

例如假设您在每个捆绑包上创建了一个抽象异常:

abstract class BundleOneException extends \Exception {}

(BundleTwo 和 BundleThree 也一样)。现在在每个 bundle 上,你抛出的每个异常都应该是这个异常的扩展。

然后你可以对每个听众做:

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

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

    // otherwise, do your thing

}

所有侦听器都在侦听所有异常,但它们只会对适当的异常采取行动。

这是最实用的处理方法。是的,您需要每个包在它们抛出的异常类型上保持一致;但是抛出一般异常并不是很好的做法(正如这种情况所证明的那样)。

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

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

  2. 如果你知道你想在你的听众中捕获哪些特定的异常,你可以在你的每个包中子class那些,并且只在 ExceptionListeners 中继续如果 class 匹配,.

  3. 您还可以获取异常堆栈跟踪并使用 Exception::getTrace 进行反省,并进行一些迭代挖掘以查看您的侦听器中捕获的异常是否实际上是在特定文件中抛出的,也许通过查看那里的 file 字段。

但总而言之,对我来说需要这样的东西看起来像是应用程序代码中关注点分离原则的问题。看起来您正在将捆绑包视为单独的应用程序,但据我所知,这不是针对捆绑包的分解方式。 Symfony 的最佳实践现在建议只使用 AppBundle,但即使你想添加更多的包,这样做的原因仍然是按域拆分你的代码,这将自动导致具有 subclass在每个包中编辑异常。