laravel api not showing message from request validation - laravel

im having problems with error handler in my backend laravel api, don't show error message from validation.
routes/api
<?php
Route::group([
'middleware' => 'api',
], function ($router) {
Route::post('access/sign-up', 'AuthenticationController#signUp');
});
AuthenticationController
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\SignUpRequest;
use Illuminate\Http\Request;
use App\User;
class AuthenticationController extends Controller
{
/**
* Create a new AuthenticationController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:api', ['except' => ['signUp']]);
}
/**
*
*
* #return \Illuminate\Http\JsonResponse
*/
public function signUp(SignUpRequest $request)
{
//User::create($request->all());
return response()->json([
'data' => 'Usuario creado correctamente.'
]);
}
}
SignUpRequest
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SignUpRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required|email|unique:users',
'firstName' => 'required',
'password' => 'required',
];
}
}
The thing is that when by postman i send password in blank or not send mail for example it send me to main page insted of sending me a json with all the errors like before. I don't know what to do.
I tryed with custom message in SignUpRequest, but that's not the problem, think some kind of redirect in error handler.

You need to check just one setting must add Accept Type in header data in Postman
Accept : application/json
that is work in my case...

Just add that code to SignUpRequest
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json($validator->errors(), 422));
}

Using the Form request; If validation fails, a redirect response will be generated to send the user back to their previous location. That's why you are redirecting back to the page instead of the response JSON.
Laravel have one protected method "failedValidation" method. Overwrite this method in your form request class.
protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{
throw new \Illuminate\Validation\ValidationException(response()->json($validator->errors(), 422));
}

Update for laravel 8, the first parameter in ValidationException is the Validator class:
protected function failedValidation(Validator $validator)
{
throw new ValidationException($validator, response()->json($validator->errors(), 422));
}

TL;DR Add the following header: Accept: application/json
As mentioned by a few users over here, by default, when a Form Request fails, the application will attempt to redirect the user back to their previous location. That's why you're receiving a webpage instead of a JSON response.
We can also override the "failedValidation" method. But I would recommend setting the following header on the request Accept: application/json.
Laravel will return the appropriate response based on Accept header. For application/json Laravel will return a JSON response with form errors.

Simply, in your App\Exceptions\Handler, you have to register your custom exception handling in register() method:
public function register() {
$this->renderable( function ( ValidationException $ex, $request ) {
$response = [
'ErrorCode' => 'my_error_code',
'ErrorMessage' => $ex->validator->errors()
];
return response()->json( $response );
} );
}

add this method to your formRequest class. It works in laravel 9
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class PostRequest extends FormRequest
{
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json([
'success' => false,
'message' => 'Validation errors',
'data' => $validator->errors(),
]));
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
switch ($this->method()) {
case 'GET':
case 'DELETE':{
return [];
}
case 'POST':{
return [
'title' => 'string|unique:posts|required',
'body' => 'required',
'image' => 'string|nullable',
];
}
case 'PUT':{
return [
'title' => 'string|unique:posts|required',
'body' => 'required',
'image' => 'string|nullable',
];
}
}
}
}

Just add that code to App\Exceptions\Handler:
public function render($request, Exception $exception)
{
if ($exception instanceof ValidationException) {
return response()->json([
'status' => false,
'error' => [
'type' => 'form',
'code' => 400,
'description' => 'Bad request.',
'detail' => $exception->validator->errors()
]
], 422);
}
return parent::render($request, $exception);
}

Related

laravel Form request validation return 404 error

i'm new to laravel , hope someone could help me with this problem ,
i've created a request class to validate my inputs . But when the validation fails it doesn't return any error messages instead showing a 404 error.
my request class , recoverIdRequest
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class recoverIdRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'dob' => 'required',
'email' => 'required',
];
}
}
and here's my controller : testController
class testController extends Controller
{
/**
*
* #param \App\Http\Requests\recoverIdRequest $request
* #return Illuminate\Http\Response
*/
public function test(recoverIdRequest $request)
{
$validated = $request->validated();
$dob = $request->input('dob');
$new_dob = Carbon::parse($dob)->format('Y-m-d');
$email = $request->input('email');
$exist =Appl_students::where('email', $email)
->whereBetween('dob', [$new_dob, $new_dob])
->select('id', 'first_name')
->first();
if ($exist == null) {
return response()->json(['data' => $exist, 'success' => false, 'message' => "User not found"]);
} else {
$date_of_birth = Carbon::parse($dob)->format('d-m-Y');
$institute =Master::select(
'institution_name', 'website_url', 'institution_place',
'institution_post', 'institution_district', 'institution_pin',
'institution_state', 'institution_phone', 'institution_email')
->first();
return $institute;
Mail::to($email)->send(new RecoverApplicationId($exist->id, $date_of_birth, $exist->first_name, $institute->institution_name));
return response()->json(['data' => $exist, 'success' => true, 'message' => "Application ID has seen sent to registered mail"]);
}
}
}
and this is the response in postman when the validation fails :
routes/api.php
Route::group([ 'prefix'=>'modelTesting', ], function() {
Route::post('test/{id}' [testController::class,'test'])->middleware(['auth:api', 'scope:admin']);
});
Resolved
it was a problem with postman headers,i was able to fix the issue using the following headers :
Accept: application/json
X-Requested-With: XMLHttpRequest
You should follow the naming convention first in all your classes.
As the information not very much clear but it should return 422 error status. It might be the problem that when validation is failed then it is trying to redirect none existence URL. Please check the type of method you are using in postman to call the api. If it not resolved please paste the request data from the postman. And the routes.php
It does not give 404, if the validation process is not successful, validation redirects back to the previous page, in your case it gives 404 because there is no rest API and a previous page ... let's agree here
it's very natural and you just have to write a small validation method for it
try it, add this method to your form request class(recoverIdRequest) and try again
/**
* Returns validations errors.
*
* #param Validator $validator
* #throws HttpResponseException
*/
protected function failedValidation(Validator $validator)
{
// you can debug with dd() in this method
if ($this->wantsJson() || $this->ajax()) {
throw new HttpResponseException(response()->json($validator->errors(), 422));
}
parent::failedValidation($validator);
}
second step you should change handler
app/exceptions/Handler.php
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);
}

How to use the ignore rule in Form Request Validation

this is PostsRequest.php in http/request:
<?php
namespace App\Http\Requests;
use App\Post;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class PostsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => ['required','max:255', Rule::unique('posts')->ignore($this->id)],
'slug' => ['required', Rule::unique('posts')->ignore($this->id),],
'content' => 'required',
'type' => 'required|in:blog,download,page',
'status' => 'required',
];
}
}
and this is edit() method in PostController.php
public function update(PostsRequest $request, $id)
{
$validated = $request->validated();
$validated['user_id'] = auth()->user()->id;
$post = Post::find($id)->fill($validated);
$post->save();
return redirect()->action('PostController#index');
}
Problem: show error in update page that this value is already exists.
who to resolve problem unique fields in edit form?
Problem Solved
change:
Rule::unique('posts')->ignore($this->route('id'))
with:
Rule::unique('posts')->ignore($this->route('post'))
If you're wanting to resolve the $id from the route then you can use the route() method in your request class e.g.
Rule::unique('posts')->ignore($this->route('id'))

How to add errors after FormRequests validation?

How to add errors after FormRequests validation?
password_repository->update() will return an error if the current passwords entered do not match.
password_repository->update() calls an external API.
I want to add an error in the controller depending on the return value of the repository.
In PasswordRequest, validation after calling the external API cannot be described, so I am in trouble.
For this reason I want to add an error in the controller after doing password_repository->update().
PasswordController.php
public function completeEdit(PasswordRequest $request)
{
$input = $request->only(['password', 'new_password']);
$data = $this->password_repository->update($input);
//I want to add an error at this point!!!
return view('pages.password.edit.complete');
}
}
PasswordRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PasswordRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'password' => 'required',
'new_password' => 'required|confirmed',
'new_password_confirmation' => 'required',
];
}
}
Redirect with errors could help you.
return redirect()->back()->withErrors([
'Password not correct',
]);
Or return to a specific route.
return redirect()->route('password.create')->withErrors([
'Password not correct',
]);

Laravel Api does not send required error json message from Request class

Request Class
class LoginRequest extends FormRequest
{
public function wantsJson() {
return true;
}
public function authorize() {
return true;
}
public function rules() {
$validators = [
'email' => 'required',
'password' => 'required'
];
return $validators;
}
public function failedValidation(\Illuminate\Contracts\Validation\Validator $validator) {
if($validator->fails()) {
//print_r($validator->errors());
//die();
}
return parent::failedValidation($validator);
}
}
I have an api written in Laravel. I am trying to test the validation through Postman extension. When I submit some values of email and password, it works. I get the message that the credentials exists or not.
In case, I don't submit the values, then, there is no json messagebag returned.
I can confirm that there are validation error messages in MessageBag. Here is the screenshot. If the screenshot is not clear then please click it see it.
Another strange things is that the status code returned is 200
Please let me know if you need more info
In my situation I setup my Laravel API like this.
in my App\Exceptions\Handler
public function render($request, Exception $exception)
{
// return parent::render($request, $exception);
$rendered = parent::render($request, $exception);
if ($exception instanceof ValidationException) {
$json = [
'error' => $exception->validator->errors(),
'status_code' => $rendered->getStatusCode()
];
} elseif ($exception instanceof AuthorizationException) {
$json = [
'error' => 'You are not allowed to do this action.',
'status_code' => 403
];
}
else {
// Default to vague error to avoid revealing sensitive information
$json = [
'error' => (app()->environment() !== 'production')
? $exception->getMessage()
: 'An error has occurred.',
'status_code' => $exception->getCode()
];
}
return response()->json($json, $rendered->getStatusCode());
}
also import this on top
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
It helps to format the errors into JSON format.
My LoginRequest looks like this (simple)
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required|email',
'password' => 'required'
];
}
}

Validation fileds from ajax request [Laravel 5]

Here is my validation request :rules
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Support\Facades\Auth;
class UpdateCommentRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize() {
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules() {
$user = Auth::user()->id;
return [
'comment' => 'required|between:15,600',
'projectID' => "required|exists:project_group,project_id,user_id,$user|numeric",
'order' => "required|numeric",
'level' => "required|numeric"
];
}
}
And in my model I have like this:
public function apiUpdateComment(UpdateCommentRequest $request){
$comment = Comment::find(Input::get("order"));
$comment->text = Input::get('comment');
if($comment->save()){
return 'success';
}
}
This fileds I need to validate agins rules array:
array(
'comment' => Input::get('comment'),
'projectID' => Input::get('projectID'),
'order' => Input::get("order"),
'level' => Input::get("level"),
);
I need to check if all rules are ok and then update comment... Anyone can help?
public function apiUpdateComment(UpdateCommentRequest $request){
$comment = Comment::find($request->get("order"));
$comment->text = $request->get('comment');
if($comment->save()){
return 'success';
}
}
The logic behind the code:
A post request is send the the server and the route file sends it the the apiUpdateComment with all variables inside the $request. But before the code of the function is executed the validator checks the rules in your UpdateCommentRequest. If the test fails it will return errors. If it pass a comment with the id will be updated.

Resources