6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ある入力項目に複数のルールを設定している状態で、1つでもエラーを検知した場合は後続のルールを適用しないで打ち切る方法

Posted at

やりたいこと

  • ある入力項目に複数のバリデーションルールを設定する
  • N個目のルールがクリアできたらN+1個目のルールでバリデーション
  • もしバリデーションエラーになったら、後続のバリデーションは打ち切る

解決方法

bailルールを入れておけばよい。
https://laravel.com/docs/5.4/validation (Stopping On First Validation Failureの箇所)

'input' => 'bail|required|date_format:Y-m-d|custom_rule1|・・・'

bailが何をしているのか?

ValidatesAttributesValidatorあたりを見ればわかる。

ValidatesAttributes.php
    /**
     * "Break" on first validation fail.
     *
     * Always returns true, just lets us put "bail" in rules.
     *
     * @return bool
     */
    protected function validateBail()
    {
        return true;
    }

ValidatesAttributes::validateBailbail()自体には特に意味がなく常にtrueを返している。
色々と制御しているのはValidator::passes()、Validator::shouldStopValidating()。

Validator.php
    /**
     * 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;
                }
            }
        }

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

    /**
     * Check if we should stop further validations on a given attribute.
     *
     * @param  string  $attribute
     * @return bool
     */
    protected function shouldStopValidating($attribute)
    {
        if ($this->hasRule($attribute, ['Bail'])) {
            return $this->messages->has($attribute);
        }

        if (isset($this->failedRules[$attribute]) &&
            in_array('uploaded', array_keys($this->failedRules[$attribute]))) {
            return true;
        }

        // In case the attribute has any rule that indicates that the field is required
        // and that rule already failed then we should stop validation at this point
        // as now there is no point in calling other rules with this field empty.
        return $this->hasRule($attribute, $this->implicitRules) &&
               isset($this->failedRules[$attribute]) &&
               array_intersect(array_keys($this->failedRules[$attribute]), $this->implicitRules);
    }

Validator::passes()からValidator::shouldStopValidating()を呼び出している。
passes():バリデーションのメインに当たる関数
shouldStopValidating():bailルールを含んでいる場合は、現在格納されているエラーメッセージ配列を確認して何らかの値が入っていれば呼び元にtrueを返すようにしている。
(実際には他にも色々やっているが関係のある処理だけ抜粋)

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?