Is there a clean, easy way to throw php exceptions through a json response jquery/ajax call.
-
2Why do you want to throw an exception? It would likely be better to return an error state that does not trigger an exception. – doublesharp Oct 02 '12 at 15:30
-
2I mean I have try catch on the server side, and I want to put the error message into the json response. – madphp Oct 02 '12 at 15:33
5 Answers
You could do something like this in PHP (assuming this gets called via AJAX):
<?php
try {
if (some_bad_condition) {
throw new Exception('Test error', 123);
}
echo json_encode(array(
'result' => 'vanilla!',
));
} catch (Exception $e) {
echo json_encode(array(
'error' => array(
'msg' => $e->getMessage(),
'code' => $e->getCode(),
),
));
}
In JavaScript:
$.ajax({
// ...
success: function(data) {
if (data.error) {
// handle the error
throw data.error.msg;
}
alert(data.result);
}
});
You can also trigger the error:
handler of $.ajax() by returning a 400 (for example) header:
header('HTTP/1.0 400 Bad error');
Or use Status:
if you're on FastCGI. Note that the error:
handler doesn't receive the error details; to accomplish that you have to override how $.ajax()
works :)

- 170,779
- 38
- 263
- 309
-
-
1
-
You might want to throw in the `'stack' => $e->getTrace()` as well so you get a nice array of the stack too. – Arno van Oordt Oct 11 '17 at 10:49
-
1@ArnovanOordt gotta be careful with that, because stack traces tend to reveal code details – Ja͢ck Oct 11 '17 at 10:58
-
Facebook do something in their PHP SDK where they throw an exception if a HTTP request failed for whatever reason. You could take this approach, and just return the error and exception details if an exception is thrown:
<?php
header('Content-Type: application/json');
try {
// something; result successful
echo json_encode(array(
'results' => $results
));
}
catch (Exception $e) {
echo json_encode(array(
'error' => array(
'code' => $e->getCode(),
'message' => $e->getMessage()
)
));
}
You can then just listen for the error
key in your AJAX calls in JavaScript:
<script>
$.getJSON('http://example.com/some_endpoint.php', function(response) {
if (response.error) {
// an error occurred
}
else {
$.each(response.results, function(i, result) {
// do something with each result
});
}
});
</script>

- 38,379
- 25
- 128
- 201
If all the errors should be treated in the same way (showing a dialog for example). You can do it this way:
PHP End:
public function throwJsonException($msg) {
echo json_encode(array('error'=> true, 'msg' => $msg));
}
throwJsonException('login invalid!');
jQuery End:
$(document).ajaxSuccess(function(evt, request, settings){
var data=request.responseText;
if (data.length>0) {
var resp=$.parseJSON(data);
if (resp.error)
{
showDialog(resp.msg);
return;
}
}
});

- 2,759
- 2
- 22
- 33
As a complement to the previous answers, instead of repeating the same code for json encoding in all your exceptions, you could set an exception handler to be used only in the needed scripts. For instance:
function ajaxExceptionHandler($e) {
echo json_encode(array(
'error' => array(
'code' => $e->getCode(),
'msg' => $e->getMessage())
));
}
Then, in your ajax handler,
set_exception_handler('ajaxExceptionHandler');

- 1,068
- 12
- 20
I use this approach to convert Exceptions to JSON:
<?php
namespace MyApp\Utility;
use Throwable;
trait JsonExceptionTrait
{
public function jsonException(Throwable $exception)
{
return json_encode([
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTrace()
]);
}
}
then, simply in my controllers:
<?php
namespace MyApp\Controller;
use MyApp\Utility\JsonExceptionTrait;
class UserController extends AbstractController
{
use JsonExceptionTrait;
/**
* @param int $userId
* @return JsonResponse
*/
public function getAction(int $userId): JsonResponse
{
try {
$user = $this->userService->getUser($userId);
return new Response($user);
} catch (EntityNotFoundException $exception) {
return new Response(
$this->jsonException($exception),
JsonResponse::HTTP_NOT_FOUND
);
}
}

- 364
- 1
- 5
- 13