Skip to content
8 changes: 6 additions & 2 deletions src/Illuminate/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,6 @@ public function passes()
$this->validateAttribute($attribute, $rule);

if ($this->shouldBeExcluded($attribute)) {
$this->removeAttribute($attribute);

break;
}

Expand All @@ -441,6 +439,12 @@ public function passes()
}
}

foreach ($this->rules as $attribute => $rules) {
if ($this->shouldBeExcluded($attribute)) {
$this->removeAttribute($attribute);
}
}

// 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.
Expand Down
33 changes: 33 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8199,6 +8199,39 @@ public function testExclude($rules, $data, $expectedValidatedData)
$this->assertSame($expectedValidatedData, $validator->validated());
}

public function testExcludeBeforeADependentRule()
{
$validator = new Validator(
$this->getIlluminateArrayTranslator(),
[
'profile_id' => null,
'type' => 'denied',
],
[
'type' => ['required', 'string', 'exclude'],
'profile_id' => ['nullable', 'required_if:type,profile', 'integer'],
],
);

$this->assertTrue($validator->passes());
$this->assertSame(['profile_id' => null], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
[
'profile_id' => null,
'type' => 'profile',
],
[
'type' => ['required', 'string', 'exclude'],
'profile_id' => ['nullable', 'required_if:type,profile', 'integer'],
],
);

$this->assertFalse($validator->passes());
$this->assertSame(['profile_id' => ['validation.required_if']], $validator->getMessageBag()->getMessages());
}

public function testExcludingArrays()
{
$validator = new Validator(
Expand Down