86
votes

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?
}
5
What about extending the validation of laravel to add your complex treatment like yhis Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; }); then you can add the foo rule in the rules 'csv_file' => 'required|foo|mimes:csv,txt', ??Maraboc
@Svish Do you have your custom validation class to throw on validation error ?ako
@Svish I think madalinivascu's solution is your answer.ako
you can catch the error message in catch block and do your stuff. like this try { //my stuff } catch (Exception $ex) { echo $ex->getMessage(); //Message //$ex->getFile(); //File //$ex->getLine(); //Line }Raunak Gupta
or you can also do you custom validation and throw the error and then handle it in catch like this try { $validator = Validator::make($request, ['csv_file' => 'required|mimes:csv,txt']); if ($validator->fails()) { throw new Exception(implode('<br>', $validator->errors()->all()), 999); } } catch (Exception $ex) { if ($ex->getCode() == 999) { //this is a custom error } echo $ex->getMessage(); //Message }Raunak Gupta

5 Answers

203
votes

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

Laravel <= 6.2 this solution worked for me:

$validator = Validator::make([], []); // Empty data and rules fields
$validator->errors()->add('fieldName', 'This is the error message');
throw new ValidationException($validator);
17
votes

Simply return from controller:

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

or:

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

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()]));
}
2
votes

For Laravel 5.8:

.

The easiest way to throw an exception is like this:

throw new \ErrorException('Error found');