Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of After Validation Hook in Laravel 5

I'm learning Laravel 5 and trying to validate if an email exists in database yet then add some custom message if it fails. I found the After Validation Hook in Laravel's documentation

$validator = Validator::make(...);

$validator->after(function($validator) use ($email) {
    if (emailExist($email)) {
        $validator->errors()->add('email', 'This email has been used!');
    }
});

if ($validator->fails()) {
    return redirect('somewhere')
        ->withErrors($validator);
}

but I don't really understand what this is. Because I can simply do this:

//as above

if (emailExist($email)) {
    $validator->errors()->add('email', 'This email has been used!');
}

//redirect as above

It still outputs the same result. When should I use the 1st one to validate something instead of the 2nd one?

like image 422
Sy Tran Avatar asked Nov 17 '15 20:11

Sy Tran


2 Answers

The point of the first method is just to keep everything contained inside of that Validator object to make it more reusable.

Yes, in your case it does the exact same thing. But imagine if you wanted to validate multiple items.

foreach ($inputs as $input) {
    $validator->setData($input);

    if ($validator->fails()) { ... }
}

In your case you will have to add that "if" check into the loop. Now imagine having to run this validation in many different places (multiple controllers, maybe a console script). Now you have this if statement in 3 different files, and next time you go to modify it you have 3x the amount of work, and maybe you forget to change it in one place...

I can't think of many use cases for this but that is the basic idea behind it.

By the way there is a validation rule called exists that will probably handle your emailExist() method

$rules = [
    'email' => 'exists:users,email',
];

http://laravel.com/docs/5.1/validation#rule-exists

like image 102
andrewtweber Avatar answered Nov 14 '22 22:11

andrewtweber


There may be many scenarios where you may feel it's requirement.

Just assume that you are trying to build REST api for a project. And you have decided that update request method will not have any required rule validation for any field in request (as there maybe many parameters and you do not want to pass them all just to change one column or maybe you do not have all the columns because you aren't allowed access to it) .

So how will you handle this validation in UpdatePostRequest.php class where you have put all the validation rules in rules() method as given in code.

Further more there may be requirement that sum of values of two or more request fields should be greater or less than some threshold quantity. Then what?

I agree that you can just check it in controller and redirect it from there but wouldn't it defeat the purpose of creating a dedicated request class if we were to do these checks in controllers.

What I feel is controllers should be clean and should not have multiple exit points based on validation. These small validation checks can be handled in request class itself by creating a new Rule or extending your own custom validation or creating after validation hooks and all of them have their unique usage in Laravel.

Therefore what you may want to to do here is create a validation hook where it's assigned is to check whether request is empty or not like the example given below

public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            if (empty($this->toArray())) {
                $validator->errors()->add('body', 'Request body cannot be empty');
            }
             if (!$this->validateCaptcha()) {
                $validator->errors()->add('g-recaptcha-response', 'invalid');
            }


        });
    }

And here is the full example for it.

<?php

namespace App\Http\Requests\Posts;


use App\Helpers\General\Tables;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdatePostRequest extends FormRequest
{
    public function authorize()
    {
        return auth()->user()->can('update-post', $this);
    }

    public function rules()
    {
        return [
            'name' => ['string', 'min:3', 'max:255'],

            'email' => ['string', 'email', 'min:3', 'max:255'],
            'post_data' => ['string', 'min:3',  'max:255'],
        ];
    }

    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            if (empty($this->toArray())) {
                $validator->errors()->add('body', 'Request body cannot be empty');
            }
        });
    }


}

Thanks..

like image 34
Shikhar Tiwari Avatar answered Nov 15 '22 00:11

Shikhar Tiwari