Zend框架:如何处理Ajax请求中的异常?

5
通常当抛出异常时,错误控制器会接管并显示带有常规公共页眉和页脚的错误页面。
在Ajax请求中不希望出现这种情况。因为在出现错误的情况下,整个HTML页面都会被发送过来。而且在直接将HTTP响应内容加载到一个div中的情况下,这种情况更加不可取。
相反,在Ajax请求的情况下,我只想收到由异常引发的“实际错误”。
如何做到这一点?
我认为,一种肮脏的方法可能是:设置一个Ajax请求中的变量并相应地进行处理。但这不是一个好的解决方案。
3个回答

3
如果您使用contextSwitch或者ajaxContext动作助手来编码您的错误(可能关闭autoJsonSerialization),您可以将错误作为JSON/XML对象简单地传递回去。
参考链接:http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch
class Error_Controller extends Zend_Controller{
    public function errorAction(){
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->addActionContext($this->getRequest()->getActionName(),'json')
            ->initContext();
        $errors = $this->_getParam('error_handler');
        $this->view->exception = $errors->exception;
    }
}

接下来,您需要在每个AJAX请求中传递一个format=json参数,或者设置一个路由链以自动附加它。

对于“稍微”更安全的设置,您可以使用ajaxContext作为助手,并且仅为具有XMLHttpRequest头的请求提供json服务。


1
能否提供一个 JSON 的代码片段?那会非常有帮助。谢谢。 - understack

2

我试着使用之前的两个答案,但遇到了问题。其中有几个原因导致我遇到麻烦,其中一个是当一切顺利时,我想要能够从我的常规控制器返回原始HTML。

这是我最终想出的解决方案:

class ErrorController extends Zend_Controller_Action
{
    public function init()
    {
        // Add the context to the error action
        $this->_helper->contextSwitch()->addActionContext('error', 'json');
    }

    public function errorAction()
    {
        // Check if this is an Ajax request
        if ($this->getRequest()->isXmlHttpRequest()) {

            // Force to use the JSON context, which will disable the layout.
            $this->_helper->contextSwitch()->initContext('json');

            //   Note: Using the 'json' parameter is required here unless you are
            //   passing '/format/json' as part of your URL.
        }

        // ... standard ErrorController code, cont'd ...

1
我使用的代码为非 Ajax 请求保留了错误处理,并保持了 "displayExceptions" 选项的完整性。它与常规错误处理程序完全相同,在 application.ini 文件中激活 "displayExceptions" 时,堆栈跟踪和请求参数也会被发送回来。在发送 JSON 数据方面有很大的灵活性 - 你可以创建一个自定义类,使用具有 JSON 视图助手的视图等等。
class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        if ($this->getRequest()->isXmlHttpRequest()) {
            $this->_helper->contextSwitch()->initJsonContext();

            $response = array('success' => false);

            if ($this->getInvokeArg('displayExceptions') == true) {
                // Add exception error message
                $response['exception'] = $errors->exception->getMessage();

                // Send stack trace
                $response['trace'] = $errors->exception->getTrace();

                // Send request params
                $response['request'] = $this->getRequest()->getParams();
            }

            echo Zend_Json::encode($response);
            return;
        }

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:

                // 404 error -- controller or action not found
                $this->getResponse()->setHttpResponseCode(404);
                $this->view->message = 'Page not found';
                break;
            default:
                // application error
                $this->getResponse()->setHttpResponseCode(500);
                $this->view->message = 'Application error';
                break;
        }

        // conditionally display exceptions
        if ($this->getInvokeArg('displayExceptions') == true) {
            $this->view->exception = $errors->exception;
        }

        $this->view->request = $errors->request;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接