Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

techpaysol's avatar

Validation "bail" rule doesn't work

Hi!

I tried to add the "bail" rule in my request class and found that it does nothing. The validation still goes to the next parameters even if one of them fails. So I searched the issue over the internet and nobody solved it. Struggling to find a solution for this issue I found that in Laravel's Validator class there's a method which checks if the attribute rule passes and if should stop the validation on fail. I wanted create a custom Validator, but this is a way to complex situation.

The method in charge is "passes()":

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

        $this->distinctValues = [];

        // 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;
                }
            }
        }

        // 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();
    }

... which breaks only the rules iteration and continues to iterate through the attributes.

I would have override this as follows:

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

        $this->distinctValues = [];

        // 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);
            
            $break = false;
            foreach ($rules as $rule) {
                $this->validateAttribute($attribute, $rule);

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

        // 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();
    }

...but since this is a vendor class, I cannot permanently modify it.

So, Laravel tech guys... please update the functionality to make it work (maybe you have a better solution for this).

Thanks, Coco

0 likes
0 replies

Please or to participate in this conversation.