Svish
Svish

Reputation: 157981

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

Have a method that's importing CSV-data into a Database. I do some basic validation using

class CsvImportController extends Controller
{
    public function import(Request $request)
    {   
        $this->validate($request, [
            'csv_file' => 'required|mimes:csv,txt',
        ]);

But after that things can go wrong for more complex reasons, further down the rabbit hole, that throws exceptions of some sort. I can't write proper validation stuff to use with the validate method here, but, I really like how Laravel works when the validation fails and how easy it is to embed the error(s) into the blade view etc, so...

Is there a (preferably clean) way to manually tell Laravel that "I know I didn't use your validate method right now, but I'd really like you to expose this error here as if I did"? Is there something I can return, an exception I can wrap things with, or something?

try
{
    // Call the rabbit hole of an import method
}
catch(\Exception $e)
{
    // Can I return/throw something that to Laravel looks 
    // like a validation error and acts accordingly here?
}

Upvotes: 150

Views: 261358

Answers (8)

Hashim Aziz
Hashim Aziz

Reputation: 6052

In Laravel 8 and above, the following works in both a controller and a model:

return back()->withErrors(["email" => "Are you sure the email is correct?"])->withInput();

This will return the user to the view they were on previously, displaying the specified error for the field email if it exists, and re-populate the fields with the information the user just entered, preventing them from needing to fill out the form again.

Another functionally similar alternative would be to do something like this:

throw new ValidationException::withMessages(['email' => 'Are you sure the email is correct?'])->withInput();

Upvotes: 19

Kachkol Asa
Kachkol Asa

Reputation: 432

Although my answer might be a little different than what you are asking but it might help others who land up on this page when trying to validating customly. If you want to validate with custom validations then you can something like this:

$validator = Validator::make($request->all(), [
    "zips" => [
        "required",
        "array",
        function ($attribute, $value, $fail) use ($request) {
            if (count($value) > 1 && !$request->user()->hasActiveSubscription()) {
                $fail('You must have an active subscription to add multiple zips.');
            }
        }
    ],
]);

Upvotes: -1

Mārtiņš Briedis
Mārtiņš Briedis

Reputation: 17752

Laravel <= 9.* this solution worked for me:

// Empty data and rules
$validator = \Validator::make([], []);

// Add fields and errors
$validator->errors()->add('fieldName', 'This is the error message');

throw new \Illuminate\Validation\ValidationException($validator);

Upvotes: 41

Goper Leo Zosa
Goper Leo Zosa

Reputation: 1283

As of on Laravel 5.5 > you can use

throw_if - throws the given exception if a given boolean expression evaluates to true

$foo = true;
throw_if($foo, \Exception::class, 'The foo is true!');

or

throw_unless - throws the given exception if a given boolean expression evaluates to false

$foo = false;
throw_unless($foo);

See here

Upvotes: 2

Mantas D
Mantas D

Reputation: 4150

Simply return from controller:

return back()->withErrors('your error message');

or:

throw ValidationException::withMessages(['your error message']);

Upvotes: 43

Erin
Erin

Reputation: 5825

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']);

Upvotes: 337

madalinivascu
madalinivascu

Reputation: 32354

you can try a custom message bag

try
{
    // Call the rabbit hole of an import method
}
catch(\Exception $e)
{
    return redirect()->to('dashboard')->withErrors(new \Illuminate\Support\MessageBag(['catch_exception'=>$e->getMessage()]));
}

Upvotes: 5

Syamsoul Azrien
Syamsoul Azrien

Reputation: 2742

For Laravel 5.8:

.

The easiest way to throw an exception is like this:

throw new \ErrorException('Error found');

Upvotes: 14

Related Questions