I\'m using FormRequest to validate from which is sent in an API call from my smartphone app. So, I want FormRequest alway return json when validation fail.
I saw th
i just override the failedValidation
function
protected function failedValidation(Validator $validator)
{
if ($this->wantsJson()) {
throw new HttpResponseException(
Response::error(__('api.validation_error'),
$validator->errors(),
470,
[],
new ValidationException)
);
}
parent::failedValidation($validator);
}
So my custom output sample like below:
{
"error": true,
"message": "Validation Error",
"reference": [
"The device id field is required.",
"The os version field is required.",
"The apps version field is required."
],
}
BTW Response::error dont exist in laravel. Im using macroable to create new method
Response::macro('error', function ($msg = 'Something went wrong', $reference = null, $code = 400, array $headers = [], $exception = null) {
return response()->json(//custom here);
});
It boggles my mind why this is so hard to do in Laravel. In the end, based on your idea to override the Request class, I came up with this.
app/Http/Requests/ApiRequest.php
<?php
namespace App\Http\Requests;
class ApiRequest extends Request
{
public function wantsJson()
{
return true;
}
}
Then, in every controller just pass \App\Http\Requests\ApiRequest
public function index(ApiRequest $request)
if your request has either X-Request-With: XMLHttpRequest header or accept content type as application/json FormRequest will automatically return a json response containing the errors with a status of 422.
Based on ZeroOne's response, if you're using Form Request validation you can override the failedValidation method to always return json in case of validation failure.
The good thing about this solution, is that you're not overriding all the responses to return json, but just the validation failures. So for all the other Php exceptions you'll still see the friendly Laravel error page.
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Symfony\Component\HttpFoundation\Response;
class InventoryRequest extends FormRequest
{
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response($validator->errors(), Response::HTTP_UNPROCESSABLE_ENTITY));
}
I know this post is kind of old but I just made a Middleware that replaces the "Accept" header of the request with "application/json". This makes the wantsJson()
function return true
when used. (This was tested in Laravel 5.2 but I think it works the same in 5.1)
Here's how you implement that :
Create the file app/Http/Middleware/Jsonify.php
namespace App\Http\Middleware;
use Closure;
class Jsonify
{
/**
* Change the Request headers to accept "application/json" first
* in order to make the wantsJson() function return true
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Add the middleware to your $routeMiddleware
table of your app/Http/Kernel.php
file
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'jsonify' => \App\Http\Middleware\Jsonify::class
];
Finally use it in your routes.php
as you would with any middleware. In my case it looks like this :
Route::group(['prefix' => 'api/v1', 'middleware' => ['jsonify']], function() {
// Routes
});