【问题标题】:Catching Exceptions in Zend Framework 3在 Zend Framework 3 中捕获异常
【发布时间】:2019-03-19 04:06:18
【问题描述】:

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

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

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

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

我错过了什么?有人能指出我正确的方向吗?

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

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);
     }

【问题讨论】:

    标签: php zend-framework zend-framework3


    【解决方案1】:

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

    我建议使用专门的类和工厂来区分对onBootstrap 函数使用的关注。您可以通过注册和“激活”一个 Listener 类来做到这一点,如下所示:

    '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,因为没有特殊要求。

    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;
        }
    }
    

    注意: 使用我自己的现有类进行上述操作,并按照我认为应该可以工作的方式进行了修改。但是,可能包含一两个错误;-) 不过,我认为应该为您指明正确的方向。

    【讨论】:

      猜你喜欢
      • 2013-07-08
      • 1970-01-01
      • 2014-01-23
      • 2023-01-29
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 2018-10-31
      • 2015-12-10
      相关资源
      最近更新 更多