Normally when an exception is thrown, Error controller takes command and displays error page with regular common header and footer.
This behavior is not wanted in Ajax request. Because in case of error, whole html page is sent over. And in cases where I'm directly loading the content of http response in a div, this is even more unwanted.
Instead in case of Ajax request, I just want to receive 'the actual error' thrown by exception.
How can I do this?
I think, one dirty way could be: set a var in ajax request and process accordingly. Not a good solution.
if you use either the contextSwitch
or ajaxContext
action helpers to encode your error (possibly turning off autoJsonSerialization
) you could just pass the errors back as JSON / XML objects.
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;
}
}
From there you have to either pass a format=json parameter which each AJAX request or setup a routing chain that automatically appends it.
For a 'slightly' more secure setup you could use ajaxContext as your helper and only requests that have the XMLHttpRequest
header will be served json.
I played with both of the previous answers but kept running into problems. There are a few reasons I had trouble, one of them is that I wanted to be able to return raw HTML from my regular controller when things went well.
This is the solution I eventually came up with:
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 ...
The code I use preserves error handling for non-Ajax requests, while keeping the 'displayExceptions' option intact. It is exactly like the regular error handler, in that the stack trace, and request params are also sent back when 'displayExceptions' is active within your application.ini file. There's a lot of flexibility as far as sending back the JSON data - you could create a custom class, use a view with the JSON view helper, etc.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With