How to correctly set up exception handler in Zend?

2019-05-22 15:11发布

问题:

I'm trying to redefine exception handler for a couple of my controllers in Zend (RESTful).

This is my piece of code:

abstract class RestController extends Zend_Rest_Controller
{
    public function init()
    {
        set_exception_handler(array($this, 'fault'));
    }

    public function fault($exception = null, $code = null)
    {
       echo $exception->getMessage();
    }
}

But for some reason Zend uses default template/error handling and my fault function didnt execute. Btw, I'm using module architecture. that controller is from rest module.. Zend's default error handler is from default module.

回答1:

This is an interesting question. I'm not totally sure at the moment so I'm going to research this one a bit and see what I come up with. For now there are workarounds that aren't too ghetto either. One way would be to create an abstract controller from which to extend all of your controllers in your rest module.

abstract class RestAbstractController extends Zend_Rest_Controller
{
    final public function __call($methodName, $args)
    {
        throw new MyRestException("Method {$methodName} doesn't exist", 500);
    }
}

// the extends part here is optional
class MyRestException extends Zend_Rest_Exception
{
    public function fault($exception = null, $code = null)
    {
        echo $exception->getMessage() . ' ' . __CLASS__;
        exit;
    }
}

class RestController extends RestAbstractController
{
    // method list
}

Also, I found this interesting article: http://zend-framework-community.634137.n4.nabble.com/Dealing-with-uncatched-exceptions-and-using-set-exception-handler-in-Zend-Framework-td1566606.html

Edit:

Somewhere in your bootstrap file you will need to add this:

$this->_front->throwExceptions(true);
$ex = new MyRestException();
set_exception_handler(array($ex, 'fault'));

The first line there should effectively turn off Zend's exception handling, the only thing missing is a control structure to determine if the current request is for your REST service or not. NOTE The reason this had to go in the Bootstrap.php file was that your call to set_exception_handler() in the init() function was never reached because Zend Framework threw the exception first. Placing that in the bootstrap file will counter that.



回答2:

Finally solved the problem by myself :)

From Zend documentation:

Zend_Controller_Front::throwExceptions()

By passing a boolean TRUE value to this method, you can tell the front controller that instead of aggregating exceptions in the response object or using the error handler plugin, you'd rather handle them yourself

So, correct solution is this:

abstract class RestController extends Zend_Rest_Controller
{
    public function init()
    {
        $front = Zend_Controller_Front::getInstance();
        $front->throwExceptions(true);

        set_exception_handler(array($this, 'fault'));
    }

    public function fault($exception = null, $code = null)
    {
       echo $exception->getMessage();
    }
}

We just have to add

$front = Zend_Controller_Front::getInstance();
$front->throwExceptions(true);

before set_exception_handler to make it work.