How to Manually Return or Throw a Validation Error/Exception in Laravel

How can I manually return or throw a validation error/exception in Laravel?

As of laravel 5.5, the ValidationException class has a static method withMessages that you can use:

$error = \Illuminate\Validation\ValidationException::withMessages([
'field_name_1' => ['Validation Message #1'],
'field_name_2' => ['Validation Message #2'],
]);
throw $error;

I haven't tested this, but it should work.

Update

The message does not have to be wrapped in an array. You can also do:

use Illuminate\Validation\ValidationException;

throw ValidationException::withMessages(['field_name' => 'This value is incorrect']);

Manually throw Laravel ValidationException VS FormRequestValidationException

dd($exception instanceof Exception); //gives false

I'm pretty sure this is impossible. Illuminate\Validation\ValidationException extends directly from Exception. Your result might have to do with the catch block in checkEmailExists. Just so you know, you shouldn't have to catch such exceptions inside your controller, since that is what the Exception Handler is for (app/Exceptions/Handler.php).

There shouldn't be any different behaviour on how you use this, so let me show what ways you would use such validation:

Inside a controller function

Inside controllers you have the helper $this->validate(...) available:

public function index(\Illuminate\Http\Request $request) {
$this->validate($request, [
'test' => 'required|integer'
], [
'test.integer' => 'Some custom message for when this subvalidation fails'
]);
}

This automatically throws a ValidationException and therefore should get picked up by your Exception handler. Your Exception handler will then decide whether to return a JSON response with the validation errors (this will happen when a header Accept: application/json was used for instance) or flash messages to the session such that you can show them in your templates.

Outside controllers

Sometimes it is extremely handy to use the validation for things that run outside of your controllers. These could be jobs or background tasks for instance. In those cases, you would call it like so (its basically the thing what happens in the controller function):

class SomeLibrary
{
public function doSomething() {
// Quickest way:
\Illuminate\Support\Facades\Validator::make($data, [
'test' => 'required|integer'
])->validate();

// Convoluted way:
// (see your own code in the original post)

}
}

This syntax basically does the same thing and also throws a ValidationException.

Throw a validation error immediately

Lastly, in some cases you want to immediately throw a validation exception without even needing to test any input, in that case you can use this to set the error messages:

throw \Illuminate\Validation\ValidationException::withMessages([
'amount' => 'The amount is not high enough'
]);

This will then follow the same route through the exception handler.

Laravel throw a custom ValidationException

May be you would like to try if you have field names "one_thing" and "another_thing"

$error = Illuminate\Validation\ValidationException::withMessages([
"one_thing" => ["Validation Message #1"],
"another_thing" => ['Validation Message #2']
]);

throw $error;

check the withMessages() method definition

 public static function withMessages(array $messages)
{
return new static(tap(ValidatorFacade::make([], []), function ($validator) use ($messages) {
foreach ($messages as $key => $value) {
foreach (Arr::wrap($value) as $message) {
$validator->errors()->add($key, $message);
}
}
}));
}

The keys are treated as fields name, so that the $errors you will through will be related to respective fields.

so basically like

$error = \Illuminate\Validation\ValidationException::withMessages([
'field_name_1' => ['Validation Message for field name 1'],
'field_name_2' => ['Validation Message for field name 2'],
'field_name_3' => ['Validation Message for field name 3'],
]);
throw $error;

Try this

Form code is

<form action="{{ route('test-validation') }}" method="POST">
@csrf
<input type="text" name="test" value="" />
@if( $errors->has('test') )
@foreach( $errors->get('test') as $err )
{{ $err }}
@endforeach
@endif
<input type="submit" name="submit" value="Submit" />
</form>

and in your routes/web.php

use Validator;
use Illuminate\Validation\ValidationException;
use Illuminate\Http\Request;
Route::post('test-validation', function(Request $request){

$fields = array('test' => $request->input('test'));
$rules = array('test' => 'required|min:5');

$validator = Validator::make($fields, $rules); // Empty data and rules fields
$validator->errors()->add('test', 'This is the error message for test field');
throw new ValidationException($validator);

redirect()->withErrors($validator);
})->name('test-validation');

With this code you should be able to get the errors correctly.

Laravel validation error not returning as json response

If validation fails during a traditional HTTP request, a redirect response to the previous URL will be generated.

If the incoming request is an XHR request, a JSON response containing the validation error messages will be returned.

First I suppose that /contact-us is a Web route and not an API route.

The $request->validate() default behavior on failure is to redirect you to the previous Web route with MessageBag.

To prevent that default behaviour, you need to wrap the validation process in a try-catch block and catch the Illuminate\Validation\ValidationException Exception and return error messages from [IndexController::class, 'contactForm'].

The the error messages array will automatically get converted to a JSON response.

try {
$request->validate([
'first_name' => ['required', 'string', 'min:3', 'max:255'],
'last_name' => ['required', 'string', 'min:3', 'max:255'],
'email' => ['required', 'email', 'min:3', 'max:255'],
'message' => ['required', 'string', 'min:3']
]);
} catch (\Illuminate\Validation\ValidationException $th) {
return $th->validator->errors();
}

Example respone:

{
"first_name": [
"first name field is required."
],
"last_name": [
"last name field is required."
],
"email": [
"L'E-mail field is required."
],
"message": [
"message field is required."
]
}

How to show only one error message from Laravel request rules

-For custom message


Laravel Documents customizing-the-error-messages

-For return single error message

    //In Request
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json([
'success' => false,
'message' =>$validator->errors()->first(),
'data' => null,
], 422));
}

Include extra validation in Laravel 8 using $errors Variable

You can add custom validation for this instead of if else

$request -> validate([

'folio' => 'required',
'codigo_referido_id' => ['required', function ($attribute, $value, $fail) {
if (!Empleado::find($value)) {
$fail('The '.$attribute.' is invalid.');
}
}],
'descuento_activo_id' => 'required',
'lead_id' => 'required'

]);

Ref:https://laravel.com/docs/8.x/validation#custom-validation-rules



Related Topics



Leave a reply



Submit