Skip to content

Commit

Permalink
stop on first failure support
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Feb 27, 2021
1 parent 8a14453 commit 39e1f84
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/Illuminate/Foundation/Http/FormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class FormRequest extends Request implements ValidatesWhenResolved
*/
protected $errorBag = 'default';

/**
* Indicates whether validation should stop after the first rule failure.
*
* @var bool
*/
protected $stopOnFirstFailure = false;

/**
* The validator instance.
*
Expand Down Expand Up @@ -104,7 +111,7 @@ protected function createDefaultValidator(ValidationFactory $factory)
return $factory->make(
$this->validationData(), $this->container->call([$this, 'rules']),
$this->messages(), $this->attributes()
);
)->stopOnFirstFailure($this->stopOnFirstFailure);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions src/Illuminate/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ class Validator implements ValidatorContract
*/
public $customValues = [];

/**
* Indicates if the validator should stop on the first rule failure.
*
* @var bool
*/
protected $stopOnFirstFailure = false;

/**
* All of the custom validator extensions.
*
Expand Down Expand Up @@ -373,6 +380,10 @@ public function passes()
continue;
}

if ($this->stopOnFirstFailure && $this->messages->isNotEmpty()) {
break;
}

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

Expand Down Expand Up @@ -1074,6 +1085,19 @@ public function sometimes($attribute, $rules, callable $callback)
return $this;
}

/**
* Instruct the validator to stop validating after the first rule failure.
*
* @param bool $stopOnFirstFailure
* @return $this
*/
public function stopOnFirstFailure($stopOnFirstFailure = true)
{
$this->stopOnFirstFailure = $stopOnFirstFailure;

return $this;
}

/**
* Register an array of custom validator extensions.
*
Expand Down
36 changes: 36 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5719,6 +5719,42 @@ public function testValidateFailsWithAsterisksAsDataKeys()
$this->assertSame(['data.1.date' => ['validation.date'], 'data.*.date' => ['validation.date']], $validator->messages()->toArray());
}

public function testFailOnFirstError()
{
$trans = $this->getIlluminateArrayTranslator();
$data = [
'foo' => 'bar',
'age' => 30,
];
$rules = [
'foo' => ['required', 'string'],
'baz' => ['required'],
'age' => ['required', 'min:31'],
];

$expectedFailOnFirstErrorDisableResult = [
'baz' => [
'validation.required',
],
'age' => [
'validation.min.string',
],
];
$failOnFirstErrorDisable = new Validator($trans, $data, $rules);
$this->assertFalse($failOnFirstErrorDisable->passes());
$this->assertEquals($expectedFailOnFirstErrorDisableResult, $failOnFirstErrorDisable->getMessageBag()->getMessages());

$expectedFailOnFirstErrorEnableResult = [
'baz' => [
'validation.required',
],
];
$failOnFirstErrorEnable = new Validator($trans, $data, $rules, [], []);
$failOnFirstErrorEnable->stopOnFirstFailure();
$this->assertFalse($failOnFirstErrorEnable->passes());
$this->assertEquals($expectedFailOnFirstErrorEnableResult, $failOnFirstErrorEnable->getMessageBag()->getMessages());
}

protected function getTranslator()
{
return m::mock(TranslatorContract::class);
Expand Down

0 comments on commit 39e1f84

Please sign in to comment.