简体   繁体   中英

How can I intercept exceptions in ZendFramework 3

I'm using ZendFramework 3 in my REST API project. So there are few modules and a plugin which checks an authorization status. If the authorization fails it throws an Exception.

There is no way to handle it in each controller separately using try .. catch. How can I intercept and handle the Exception and generate JSON output like this?

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

I'm a newbie in ZendFramework, that's why I have no idea how to do this. And official documentation didn't say a word about this.

There are default framework Events that are triggered including the event MvcEvent::EVENT_DISPATCH_ERROR . So, all you should do is to attach listener on that error event and return JSON response.

First, you need to register your Listener in 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
    ],
],

Second, create the file 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);
    }

}

That's all. Now on every error, your custom logics will be executed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM