如何拦截 ZendFramework 3 中的异常

How can I intercept exceptions in ZendFramework 3

我在我的 REST API 项目中使用 ZendFramework 3。所以有几个模块和一个检查授权状态的插件。如果授权失败,它会抛出异常。

无法在每个控制器中使用 try .. catch 分别处理它。如何拦截和处理异常并生成这样的 JSON 输出?

{
    message: "Access denied",
    reason: "Your token is incorrect"
}

我是 ZendFramework 的新手,所以我不知道该怎么做。官方文档对此只字未提。

default framework Events 被触发,包括事件 MvcEvent::EVENT_DISPATCH_ERROR。因此,您应该做的就是在该错误事件上附加侦听器和 return JSON 响应。

首先,您需要在 module.config.php

中注册您的监听器
// In my case module name is Api
'listeners'          => [
    Api\Listener\ApiListener::class    // Register the class listener
],
'service_manager'    => [
    'invokables' => [
        // Register the class (of course you can use Factory)
        Api\Listener\ApiListener::class => Api\Listener\ApiListener::class
    ],
],

其次,创建文件class Api/Listener/ApiListener.php

<?php

namespace Api\Listener;

use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Mvc\MvcEvent;
use Zend\Console\Request as ConsoleRequest;
use Zend\View\Model\JsonModel;


class ApiListener extends AbstractListenerAggregate
{

    public function attach(EventManagerInterface $events, $priority = 1) 
    {
        // Registr the method which will be triggered on error
        $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, 
        [$this, 'handleError'], 0);
    }


    /**
     * Return JSON error on API URI(s)
     */
    public function handleError(MvcEvent $e)
    {
        $request = $e->getParam('application')->getRequest();

        if($request instanceof ConsoleRequest){
            return;
        }

        //If you want to convert Response only on some URIs
        //$uri = $request->getUri()->getPath();
        //if(0 !== strpos($uri, '/api')){
        //    return;
        //}

        $response  = $e->getResponse();
        $exception = $e->getResult()->exception;
        $errorType = $e->getError();
        $errorCode = $exception && $exception->getCode() ? $exception->getCode() : 500;
        $errorMsg  = $exception ? $exception->getMessage() : $errorType;
        $json      = new JsonModel(['message' => $errorMsg]);

        $json->setTerminal(true);
        $response->setStatusCode($errorCode);
        $e->setResult($json);
        $e->setViewModel($json);
    }

}

就是这样。现在,对于每个错误,您的自定义逻辑都将被执行。