I have also struggled with custom exceptions and error codes when using ajax requests (jquery mobile in my case). Here is the solution I came up with, without involving overwriting the debug mode. It throws custom errors in development mode, and also optionally in production mode. I hope it helps someone:
AppExceptionRenderer.php:
<?php
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer
{
public function test($error)
{
$this->_sendAjaxError($error);
}
private function _sendAjaxError($error)
{
//only allow ajax requests and only send response if debug is on
if ($this->controller->request->is('ajax') && Configure::read('debug') > 0)
{
$this->controller->response->statusCode(500);
$response['errorCode'] = $error->getCode();
$response['errorMessage'] = $error->getMessage();
$this->controller->set(compact('response'));
$this->controller->layout = false;
$this->_outputMessage('errorjson');
}
}
}
You can leave out Configure::read('debug') > 0
if you want to display the exception in debug mode. The view errorjson.ctp is located in 'Error/errorjson.ctp':
<?php
echo json_encode($response);
?>
In this case my exception is called
TestException
and is defined as follows:
<?php
class TestException extends CakeException {
protected $_messageTemplate = 'Seems that %s is missing.';
public function __construct($message = null, $code = 2) {
if (empty($message)) {
$message = 'My custom exception.';
}
parent::__construct($message, $code);
}
}
Where I have a custom error code 2, $code = 2
, for my json response. The ajax response will cast an error 500 with following json data:
{"errorCode":"2","errorMessage":"My custom exception."}
Obviously, you also need to throw the exception from your controller:
throw new TestException();
and include the exception renderer http://book.cakephp.org/2.0/en/development/exceptions.html#using-a-custom-renderer-with-exception-renderer-to-handle-application-exceptions
This may be a bit out of scope, but to handle the ajax error response in JQuery I use:
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
//deal with my json error
});