UPDATE 10th June 2019 : I posted this article on LaravelUK Slack channel and David T gave me some valuable feedback.
You can force Laravel to always return only JSON by specifying the Accept header However, there may be instances where you want to force it regardless and the below article demonstrates how to do that.
Recently I have been using Laravel Form Request Validation instead of using inline validation. I find it much nicer to break things out into their own classes as much as possible so I was pleased when this made its way into the core framework.
If you are like me and you cannot get out of the habit of writing inline validation then don’t worry because the wonderful Jason McCreary has added an awesome feature to the Laravel Code Fixer Shift to convert inline controller validation to Form Requests.
When using Form Requests with API’s you will notice that if you hit an API route where the validation fails it will throw you to a 404 view.
My solution is to make my own FormRequest
class which I put in the root API namespace namespace App\Http\Requests\Api;
So your SearchController
which uses the SearchRequest
instead of the default Request
stays the same.
We just update the SearchRequest
to use our custom FormRequest
and not the default and we will get a nice JSON response when we have validation errors.
<?php
namespace App\Http\Requests\Api\Flight;
use Illuminate\Foundation\Http\FormRequest;
class SearchRequest extends FormRequest
{
...
}
So now our class will extend our own custom class
<?php
namespace App\Http\Requests\Api\Flight;
use App\Http\Requests\Api\FormRequest;
class SearchRequest extends FormRequest
{
...
}
So now when we hit the API endpoint we will get this
Hi, I use another method in which we no need to create seprate request and extend it in form-request.
just add below method “failedValidation” in form-request and it will transform data in JSON.
“`
use Illuminate\Http\Exceptions\HttpResponseException;
class LoginRequest extends FormRequest
{
public function rules(): array
{
return [
’email’ => [‘required’, ‘string’, ’email’],
‘password’ => [‘required’, ‘string’],
];
}
/**
* Get the error messages for the defined validation rules.*
* @param Validator $validator
* @return array
*/
protected function failedValidation(Validator $validator): array
{
throw new HttpResponseException(response()->json([
‘success’ => false,
‘errors’ => $validator->errors(),
], 422));
}
}
“`
Look at there, make an a Header Accept: application/json for implement a default logic to get a json response wich every api request
Thank you so much, I was really struggling with my validations and this one worked like a charm!
James. I just want to say that ‘You are the Best!!’, thanks so much!!
thank you, it’s great
Perfect <3
Exactly what i needed. Thanks a lot !
hi , i get errors like ReflectionException: Class App\Http\Requests\User\updateProfileRequest does not exist in file ../vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php on line 25
when i tried to call updateProfileRequest on my controller
i already try step by step like above.
btw, thanks for sharing it helps man 🙂
Hi Dedi, is this related to returning data from an API endpoint? Can you link me to a StackOverflow post where you explain your issues with a little more details and I will try to help.
Hey there,
I ran into the same issue, on your extended FormRequest class make sure you’ve imported all the required classes 🙂 i.e. Validator requires you to use Illuminate\Contracts\Validation\Validator; etc
This exception seems pointless:
“`
$errors = (new ValidationException($validator))->errors();
“`
Might as well use $validator->errors() directly instead. Also, using Illuminate\Http\JsonResponse instead of Illuminate\Http\Response for the response code seems a little wonky.
Cheers
Thanks for your feedback M. The solution I came up with works for my needs and I thought I would share to help out others. Given this articles organic search volume it would suggest others are also struggling with this. I’ll certainly have a look at your suggestions and see if I should update the article.
Was just about to implement this, and then I found this article. Super helpful. Thank you!
Thanks for the comment Alan!
Unbelievably helpful!
Thanks for your feedback Ryan!
You are great!
I can’t seem to get this to work, still being redirected if validation fails rather than seeing a JSON response.
The `failedValidation` method in my new FormRequest class doesn’t appear to be firing at all. The class is being loaded, I checked by adding a constructor with a `dd` inside of it.
Richard, did you ever get this sorted? Have you tried running dump autoload? If the constructor is getting called that only means that the class is being constructed not that the function is being called when we would expect it to. Happy to jump in a screen share with you if that would help?
Pretty nice, man!
That exatly what was I looking for.
The worst part is update all controllers, but its ok!
Pleased it helped Daniel. Thanks for reading.
you are the best =)
This is exactly what I’m looking for. I tried it out but I’m getting the following error:
“`
Declaration of App\Http\Requests\BaseFormRequest::failedValidation(Illuminate\Validation\Validator $validator) should be compatible with Illuminate\Foundation\Http\FormRequest::failedValidation(Illuminate\Contracts\Validation\Validator $validator)
“`
Apparently I gotta return the same type of data the parent method is returning. Any way around this?
Thanks
thank you.
This is really helpfule. Thanks.
Thank you so much