Laravel 5: Handle exceptions when request wants JSON
I'm going to take a shot at this one myself taking into account the answer given by @Wader and the comments from @Tyler Crompton:
app/Exceptions/Handler.php
/** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */public function render($request, Exception $e){ // If the request wants JSON (AJAX doesn't always want JSON) if ($request->wantsJson()) { // Define the response $response = [ 'errors' => 'Sorry, something went wrong.' ]; // If the app is in debug mode if (config('app.debug')) { // Add the exception class name, message and stack trace to response $response['exception'] = get_class($e); // Reflection might be better here $response['message'] = $e->getMessage(); $response['trace'] = $e->getTrace(); } // Default response of 400 $status = 400; // If this exception is an instance of HttpException if ($this->isHttpException($e)) { // Grab the HTTP status code from the Exception $status = $e->getStatusCode(); } // Return a JSON response with the response array and status code return response()->json($response, $status); } // Default to the parent class' implementation of handler return parent::render($request, $e);}
In your application you should have app/Http/Middleware/VerifyCsrfToken.php
. In that file you can handle how the middleware runs. So you could check if the request is ajax and handle that how you like.
Alternativly, and probably a better solution, would be to edit the exception handler to return json. See app/exceptions/Handler.php
, something like the below would be a starting place
public function render($request, Exception $e){ if ($request->ajax() || $request->wantsJson()) { $json = [ 'success' => false, 'error' => [ 'code' => $e->getCode(), 'message' => $e->getMessage(), ], ]; return response()->json($json, 400); } return parent::render($request, $e);}
Building on @Jonathon's handler render function, I would just modify the conditions to exclude ValidationException instances.
// If the request wants JSON + exception is not ValidationExceptionif ($request->wantsJson() && ( ! $exception instanceof ValidationException))
Laravel 5 returns validation errors in JSON already if appropriate.
The full method in App/Exceptions/Handler.php:
/** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $exception * @return \Illuminate\Http\Response */public function render($request, Exception $exception){ // If the request wants JSON + exception is not ValidationException if ($request->wantsJson() && ( ! $exception instanceof ValidationException)) { // Define the response $response = [ 'errors' => 'Sorry, something went wrong.' ]; // If the app is in debug mode if (config('app.debug')) { // Add the exception class name, message and stack trace to response $response['exception'] = get_class($exception); // Reflection might be better here $response['message'] = $exception->getMessage(); $response['trace'] = $exception->getTrace(); } // Default response of 400 $status = 400; // If this exception is an instance of HttpException if ($this->isHttpException($exception)) { // Grab the HTTP status code from the Exception $status = $exception->getCode(); } // Return a JSON response with the response array and status code return response()->json($response, $status); } return parent::render($request, $exception);}