Zend Framework 3中的捕获异常 [英] Catching Exceptions in Zend Framework 3

查看:218
本文介绍了Zend Framework 3中的捕获异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用ZF3骨架应用程序. 我想知道应该在哪里捕获全局异常.

I use the ZF3 skeletion application. I wonder where I am supposed to catch exceptions globally.

示例: 现在,如果我访问无效的路由(mysite.com/invalid-route),则应用程序会报告未捕获的期望和HTTP响应代码200

Example: Right now, if I access an invalid route (mysite.com/invalid-route), the application reports an uncaught expection and HTTP response code 200

致命错误:未捕获的Zend \ View \ Exception \ RuntimeException:未提供RouteMatch实例

Fatal error: Uncaught Zend\View\Exception\RuntimeException: No RouteMatch instance provided

我希望会触发内置404错误页面.

I would expect the build-in 404 error page to be triggered.

我想念什么?有人可以指出我正确的方向吗?

What am I missing? Can someone point me to the right direction?

使用以下代码正确记录了异常:

The exception is logged properly using the following code:

class Module implements ConfigProviderInterface
{
     const VERSION = '3.0.3-dev';

     public function onBootstrap()
     {
         $logger = new Logger();
         $writer = new Writer\Stream(__DIR__ . '/../../../data/log/error.log');
         $logger->addWriter($writer);

         // Log PHP errors
         Logger::registerErrorHandler($logger, true);

         // Log exceptions
         Logger::registerExceptionHandler($logger);
     }

推荐答案

这是您可以使用侦听器捕获的,并在早期事件MvcEvent::EVENT_ROUTE上触发.

This is something you can catch using a Listener, triggered on the early event MvcEvent::EVENT_ROUTE.

我建议使用专门的课程&工厂将对onBootstrap函数使用的关注分开.您可以通过注册和激活"一个监听器类来做到这一点,就像这样:

I would suggest using a dedicated class & Factory to separate concerns over the usage of the onBootstrap function. You'd do this by registering and "activating" a Listener class, like so:

'listeners'       => [
    // This makes sure it "gets listened to" from the very start of the application (onBootstrap)
    RouteExistsListener::class,     
],
'service_manager' => [
    'factories' => [
        // This is just what you think it is
        RouteExistsListener::class  => InvokableFactory::class,
    ],
],

由于没有特殊要求,您只能将InvokableFactory用作此侦听器.

You can use just the InvokableFactory for this Listener, as there are no special requirements.

class RouteExistsListener implements ListenerAggregateInterface
{
    /**
     * @var array
     */
    protected $listeners = [];

    /**
     * @param EventManagerInterface $events
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    /**
     * @param EventManagerInterface $events
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $events->attach(MvcEvent::EVENT_ROUTE, [$this, 'doesRouteExist'], 100);
    }

    /**
     * @param MvcEvent $event
     *
     * @return void|Response
     * @throws Exception
     */
    public function doesRouteExist(MvcEvent $event)
    {
        /** @var TranslatorAwareTreeRouteStack|TreeRouteStack $router */
        $router = $event->getRouter();
        /** @var Request $request */
        $request = $event->getRequest();
        /** @var RouteMatch|null $routeExists */
        $routeExists = $router->match($request); // Return RouteMatch|null

        if ($routeExists instanceof RouteMatch) {
            return; // Route exists - nothing to do
        }

        $url = $router->assemble([], ['name' => 'home']); // Name of your redirect route (ie. not_found/404, or something)

        /** @var Response $response */
        $response = $event->getResponse();
        $response->getHeaders()->addHeaderLine('Location', $url);
        $response->setStatusCode(302);
        $response->sendHeaders();

        $event->getApplication()->getEventManager()->attach(
            MvcEvent::EVENT_ROUTE,
            function (MvcEvent $event) use ($response) {
                $event->stopPropagation();

                return $response;
            },
            -10000
        );

        return $response;
    }
}


注意:将我自己的现有类用于上述内容,并根据我的认为进行了修改.但是,可能包含一个或两个错误;-)仍然,应该向您指出我认为的正确方向.


NOTE: Used an existing class of my own for the above and modified as I think it should work. However, might contain an error or two ;-) Still, should point you in the right direction I think.

这篇关于Zend Framework 3中的捕获异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆