Zend Framework 3中的捕获异常

时间:2018-10-14 16:22:27

标签: php zend-framework zend-framework3

我使用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);
     }

1 个答案:

答案 0 :(得分:0)

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

我建议使用专用的类和工厂来分隔对onBootstrap函数使用的关注。您可以通过注册和“激活”一个监听器类来做到这一点,就像这样:

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

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