diff --git a/src/Illuminate/Contracts/Validation/Bailable.php b/src/Illuminate/Contracts/Validation/Bailable.php new file mode 100644 index 000000000000..6c5bbe515ce2 --- /dev/null +++ b/src/Illuminate/Contracts/Validation/Bailable.php @@ -0,0 +1,7 @@ +shouldStopValidating($attribute)) { + if ($this->shouldStopValidating($attribute, $rule)) { break; } } @@ -909,9 +911,10 @@ protected function validateUsingCustomRule($attribute, $value, $rule) * Check if we should stop further validations on a given attribute. * * @param string $attribute + * @param string|ValidationRule * @return bool */ - protected function shouldStopValidating($attribute) + protected function shouldStopValidating($attribute, $rule) { $cleanedAttribute = $this->replacePlaceholderInString($attribute); @@ -919,6 +922,10 @@ protected function shouldStopValidating($attribute) return $this->messages->has($cleanedAttribute); } + if ($rule instanceof InvokableValidationRule && $rule->invokable() instanceof Bailable) { + return true; + } + if (isset($this->failedRules[$cleanedAttribute]) && array_key_exists('uploaded', $this->failedRules[$cleanedAttribute])) { return true; diff --git a/tests/Validation/ValidationRuleWithBailableTest.php b/tests/Validation/ValidationRuleWithBailableTest.php new file mode 100644 index 000000000000..bc95c420222b --- /dev/null +++ b/tests/Validation/ValidationRuleWithBailableTest.php @@ -0,0 +1,37 @@ + 'foobar'], + ['foo' => [new BailableValidationRule(), 'numeric']], + ); + $this->assertFalse($v->passes()); + $this->assertEquals( + ['foo' => ['Illuminate\Tests\Validation\BailableValidationRule' => []]], + $v->failed() + ); + } +} + +class BailableValidationRule implements ValidationRule, Bailable +{ + public function validate(string $attribute, mixed $value, Closure $fail): void + { + $fail('failed'); + } +}