Skip to content

Commit

Permalink
[8.x] Add Validator::excludeArrays() to exclude array keys that aren'…
Browse files Browse the repository at this point in the history
…t included in the validation rules (laravel#37943)

* allow excluding other array attributes that werent validated

* more tests

* use preg_quote

* formatting

* add another test

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
themsaid and taylorotwell authored Jul 10, 2021
1 parent 7a82103 commit 45d439e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
19 changes: 19 additions & 0 deletions src/Illuminate/Validation/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ class Factory implements FactoryContract
*/
protected $fallbackMessages = [];

/**
* Indicates that unvalidated array keys should be excluded, even if the parent array was validated.
*
* @var bool
*/
protected $excludeUnvalidatedArrayKeys;

/**
* The Validator resolver instance.
*
Expand Down Expand Up @@ -115,6 +122,8 @@ public function make(array $data, array $rules, array $messages = [], array $cus
$validator->setContainer($this->container);
}

$validator->excludeUnvalidatedArrayKeys = $this->excludeUnvalidatedArrayKeys;

$this->addExtensions($validator);

return $validator;
Expand Down Expand Up @@ -239,6 +248,16 @@ public function replacer($rule, $replacer)
$this->replacers[$rule] = $replacer;
}

/**
* Indicate that unvalidated array keys should be excluded, even if the parent array was validated.
*
* @return void
*/
public function excludeUnvalidatedArrayKeys()
{
$this->excludeUnvalidatedArrayKeys = true;
}

/**
* Set the Validator instance resolver.
*
Expand Down
15 changes: 14 additions & 1 deletion src/Illuminate/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ class Validator implements ValidatorContract
*/
protected $stopOnFirstFailure = false;

/**
* Indicates that unvalidated array keys should be excluded, even if the parent array was validated.
*
* @var bool
*/
public $excludeUnvalidatedArrayKeys = false;

/**
* All of the custom validator extensions.
*
Expand Down Expand Up @@ -508,7 +515,13 @@ public function validated()

$missingValue = new stdClass;

foreach (array_keys($this->getRules()) as $key) {
foreach ($this->getRules() as $key => $rules) {
if ($this->excludeUnvalidatedArrayKeys &&
in_array('array', $rules) &&
! empty(preg_grep('/^'.preg_quote($key, '/').'\.*/', array_keys($this->implicitAttributes)))) {
continue;
}

$value = data_get($this->getData(), $key, $missingValue);

if ($value !== $missingValue) {
Expand Down
56 changes: 56 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6146,6 +6146,62 @@ public function testExcludeIfWhenValidationFails($rules, $data, $expectedMessage
$this->assertSame($expectedMessages, $validator->messages()->toArray());
}

public function testExcludingArrays()
{
$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => [['name' => 'Mohamed', 'location' => 'cairo']]],
['users' => 'array', 'users.*.name' => 'string']
);
$this->assertTrue($validator->passes());
$this->assertSame(['users' => [['name' => 'Mohamed', 'location' => 'cairo']]], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => [['name' => 'Mohamed', 'location' => 'cairo']]],
['users' => 'array', 'users.*.name' => 'string']
);
$validator->excludeUnvalidatedArrayKeys = true;
$this->assertTrue($validator->passes());
$this->assertSame(['users' => [['name' => 'Mohamed']]], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => [['name' => 'Mohamed', 'location' => 'cairo']]],
['users' => 'array']
);
$validator->excludeUnvalidatedArrayKeys = true;
$this->assertTrue($validator->passes());
$this->assertSame(['users' => [['name' => 'Mohamed', 'location' => 'cairo']]], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => ['mohamed', 'zain']],
['users' => 'array', 'users.*' => 'string']
);
$validator->excludeUnvalidatedArrayKeys = true;
$this->assertTrue($validator->passes());
$this->assertSame(['users' => ['mohamed', 'zain']], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => ['admins' => [['name' => 'mohamed', 'job' => 'dev']]]],
['users' => 'array', 'users.admins' => 'array', 'users.admins.*.name' => 'string']
);
$validator->excludeUnvalidatedArrayKeys = true;
$this->assertTrue($validator->passes());
$this->assertSame(['users' => ['admins' => [['name' => 'mohamed']]]], $validator->validated());

$validator = new Validator(
$this->getIlluminateArrayTranslator(),
['users' => [1, 2, 3]],
['users' => 'array|max:10']
);
$validator->excludeUnvalidatedArrayKeys = true;
$this->assertTrue($validator->passes());
$this->assertSame(['users' => [1, 2, 3]], $validator->validated());
}

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

0 comments on commit 45d439e

Please sign in to comment.