I also struggled with custom exceptions and error codes when using ajax requests (jquery mobile in my case). Here is the solution I came across without having to overwrite debug mode. It generates user errors in development mode, and also optionally in production mode. I hope this 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 Configure::read('debug') > 0 if you want to display an exception in debug mode. The errorjson.ctp view is 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 error code 2, $code = 2 , for my json answer. The ajax response will throw a 500 error with the following json data:
{"errorCode":"2","errorMessage":"My custom exception."}
Obviously, you also need to throw an exception from your controller:
throw new TestException();
and enable the exception visualizer http://book.cakephp.org/2.0/en/development/exceptions.html#using-a-custom-renderer-with-exception-renderer-to-handle-application-exceptions
It might be a bit out of scope, but to handle the ajax error response in jQuery, I use:
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {