February 19, 2014

February 19, 2014
In this article, we are going to discuss about How to change the ErrorController to work with AJAX in Zend Framework. Zend Framework is mostly used for web application. By deafult, in Zend Framework we have a set of default ErrorControllers. If we create a web application using Zend app which makes AJAX calls , it will notify that if an error occurs, we'll get a chunk of JSON followed by the HTML for the error page. This is fine if our users hit the page in the browser but it can cause problems with our JavaScript being able to correctly decode your JSON.

By changing the ErrorController, we can easily get the JSON by using the AJAX call.

Open the file "/application/controllers/ErrorController.php". In this we need to register the errorAction in an AJAX context. It will tell the Zend Framework that if it detects an XML HTTP Request and there's a parameter called "format" with a value of "json" that it should automatically turn off the view and the layout. This will leave us with just the JSON part of the response.

If you don't have an init method in your ErrorController class, create one like this:

/** 
 * Initializes the error action to deal with AJAX responses
 * 
 * @return null
 */
public function init()
{
    $this->_helper->ajaxContext->addActionContext(
        'error', array('json')    
    )->initContext();
}

The above code does most of the work, but chances are you may want to add a few more useful pieces of information to your JSON response. Typically in any AJAX calls we'll have a success variable that indicates whether the call we made worked or not.

Add this line to the top of the errorAction method:

$this->view->success = false;

To test the above code, you can have your action your AJAX call hits throw an exception that you don't catch. This is as simple as:

throw new Exception('Foo');

If we do this, and view the JSON in chrome or Firebug, you'll see a success = false, an empty exception object, an empty request object and a very helpful message with a value of "Application error".

The empty request and exception object are because those are PHP objects that are getting set into the view within the ErrorController. In a JSON response, it may be helpful to add some more information from within those objects.

Near the end of the errorAction method, we should see some code like:

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

If you want this additional information to only be sent to the view if displayExceptions is turned on and if it's an AJAX call, you can make the following modifications.

// conditionally display exceptions        
if ($this->getInvokeArg('displayExceptions') == true) {            
    if ($this->_request->isXmlHttpRequest()) {                
        $this->view->exception  = $errors->exception
            ->getMessage();                
        $this->view->stackTrace = $errors->exception
            ->getTrace();             
    } else {                
        $this->view->exception = $errors->exception;        
    }        
}

This code will replace that empty exception object with the message from the exception. It will also create a new stackTrace object in the JSON which is an array of objects containing information about the stack trace.  It's completely up to you if you want to include that information or not.

The other empty object showing up in the JSON is the empty request. If knowing more about the request would be useful, change this

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

to this:

if ($this->_request->isXmlHttpRequest()) {
    $this->view->request = $this->_request->getParams();
} else {
    $this->view->request = $errors->request;
}

This chunk of code will replace that empty request object with an array of key: value pairs for all of the parameters in the request.

That's all there is to it. Your AJAX calls will now get a JSON response even if an error happens in one of your controllers.

I hope this helps and I look forward to hearing from you.

0 comments:

Post a Comment