Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.2] Resolve parameter fields with asterisks when validating arrays #11927

Merged
merged 4 commits into from
Feb 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/Illuminate/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ class Validator implements ValidatorContract
// 'Array', 'Boolean', 'Integer', 'Numeric', 'String',
];

/**
* The validation rules which accept other fields as parameters.
*
* @var array
*/
protected $fieldRules = [
'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll',
'RequiredIf', 'RequiredUnless', 'Confirmed', 'Same', 'Different',
];

/**
* Create a new Validator instance.
*
Expand Down Expand Up @@ -377,6 +387,13 @@ protected function validate($attribute, $rule)
return;
}

// First we will get the numeric keys for the given attribute in case the field is nested in
// an array. Then we determine if the given rule accepts other field names as parameters.
// If so, we will replace any asterisks found in the parameters with the numeric keys.
if (($keys = $this->getNumericKeys($attribute)) && $this->acceptsFields($rule)) {
$parameters = $this->normalizeParameters($parameters, $keys);
}

// We will get the value for the given attribute from the array of data and then
// verify that the attribute is indeed validatable. Unless the rule implies
// that the attribute is required, rules are not run for missing values.
Expand Down Expand Up @@ -2328,6 +2345,62 @@ protected function normalizeRule($rule)
}
}

/**
* Determine if the given rule accepts other field names as parameters.
*
* @param string $rule
* @return bool
*/
protected function acceptsFields($rule)
{
return in_array($rule, $this->fieldRules);
}

/**
* Get the numeric keys from an attribute flattened with dot notation.
*
* E.g. 'foo.1.bar.2.baz' -> [1, 2]
*
* @param string $attribute
* @return array
*/
protected function getNumericKeys($attribute)
{
if (preg_match_all('/\.(\d+)\./', $attribute, $keys)) {
return $keys[1];
}

return [];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simplify as so:

if (preg_match_all('/\.(\d+)\./', $attribute, $keys)) {
    return $keys[1];
}

return [];


In fact, $keys[1] is set even if there is no match, so you could even do:

preg_match_all('/\.(\d+)\./', $attribute, $keys);

return $keys[1];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlakoff Thanks! Are you sure there's no need to collapse the $keys[1] though?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$keys is an array of arrays, you removed the unwanted $keys[0] then collapsed the remaining of $keys (so, $keys[1]) to get a flat array.

Here, I directly pick $keys[1] which is already a flat array. You don't have to (and cannot) collapse it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlakoff thanks to your suggestions, I have committed the changes you proposed. 👍


/**
* Replace each field parameter which has asterisks with the given numeric keys.
*
* @param array $parameters
* @param array $keys
* @return array
*/
protected function normalizeParameters(array $parameters, array $keys)
{
return array_map(function ($field) use ($keys) {
return $this->replaceAsterisksWithKeys($field, $keys);
}, $parameters);
}

/**
* Replace asterisks with numeric keys.
*
* E.g. 'foo.*.bar.*.baz', [1, 2] -> foo.1.bar.2.baz
*
* @param string $field
* @param array $keys
* @return string
*/
protected function replaceAsterisksWithKeys($field, array $keys)
{
return vsprintf(str_replace('*', '%d', $field), $keys);
}

/**
* Get the array of custom validator extensions.
*
Expand Down
Loading