Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop all validations after the first failure in Laravel?

Tags:

laravel

There is a function called bail in Laravel that stops the validation upon failure. What if I want to stop ALL validations upon first failure?

For example:

$request->validate([
    'antibotprotection' => 'bail|required|exists:protectioncodes,protection_code|max:255',
    'email' => 'required|string|email|max:255|unique:users',
]);

This code will stop validation of the antibotprotection but then it will continue to validate the email and pass errors to view about the email as well, which defeats the whole purpose. How would I stop this whole validate function upon the first failure?

like image 966
Arthur Tarasov Avatar asked Nov 07 '22 03:11

Arthur Tarasov


1 Answers

./app/Validation/BailingValidator.php

<?php

namespace App\Validation;

use Illuminate\Support\MessageBag;
use Illuminate\Validation\Validator;

class BailingValidator extends Validator
{
    /**
     * Determine if the data passes the validation rules.
     *
     * @return bool
     */
    public function passes()
    {
        $this->messages = new MessageBag;

        // We'll spin through each rule, validating the attributes attached to that
        // rule. Any error messages will be added to the containers with each of
        // the other error messages, returning true if we don't have messages.
        foreach ($this->rules as $attribute => $rules) {
            $attribute = str_replace('\.', '->', $attribute);

            foreach ($rules as $rule) {
                $this->validateAttribute($attribute, $rule);

                if ($this->shouldStopValidating($attribute)) {
                    break 2;
                }
            }
        }

        // Here we will spin through all of the "after" hooks on this validator and
        // fire them off. This gives the callbacks a chance to perform all kinds
        // of other validation that needs to get wrapped up in this operation.
        foreach ($this->after as $after) {
            call_user_func($after);
        }

        return $this->messages->isEmpty();
    }
}

./app/Providers/AppServiceProvider.php

...
use App\Validation\BailingValidator;
use Illuminate\Contracts\Translation\Translator;
use Illuminate\Contracts\Validation\Factory;
use Illuminate\Support\ServiceProvider;
...
    public function boot()
    {
        /**
         * @var \Illuminate\Validation\Factory $factory
         */
        $factory = resolve(Factory::class);

        $factory->resolver(function (Translator $translator, array $data, array $rules, array $messages, array $customAttributes) {
            return new BailingValidator($translator, $data, $rules, $messages, $customAttributes);
        });
    }
...

./app/Http/Controller/SomeController.php

...
        $this->validate($request, [
            'foo' => ['bail', 'required'],
            'bar' => ['bail', 'required'],
        ]);
...

{"message":"The given data was invalid.","errors":{"foo":["The foo field is required."]}}

like image 91
Quezler Avatar answered Nov 15 '22 12:11

Quezler