-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Inconsistent validation behavior with empty arrays and nested rules #55657
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
Comments
Can you please try: $validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
'foo.bar' => 'sometimes|integer'
]); |
[image: JPEG image]
05aae16c-1749-4e44-b461-48127…
<https://drive.google.com/file/d/1wYkAVRDfx3thlgTVIODZkJmOHxjyxyJM>
…On Tue, 6 May 2025 at 16:13, comhon-project ***@***.***> wrote:
*comhon-project* created an issue (laravel/framework#55657)
<#55657>
Laravel Version
11.44.2
PHP Version
8.3
Database Driver & Version
*No response*
Description
Hello everyone,
I've noticed an unexpected behavior when validating empty arrays with
nested rules.
Here’s an example without any nested rules, which works as expected:
$validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
]);// $validated contains the "foo" key: ["foo" => []]
However, when I add a nested rule:
$validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
'foo.bar' => 'integer'
]);// $validated is empty: []
Expected:
the validated values should be the same and contain the "foo" key.
Steps To Reproduce
$validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
]);// $validated contains the "foo" key: ["foo" => []]
$validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
'foo.bar' => 'integer'
]);// $validated is empty: []
—
Reply to this email directly, view it on GitHub
<#55657>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BHFWDGVOUOBJGUD7ATXE5NT25C
8000
YQFAVCNFSM6AAAAAB4RFFD46VHI2DSMVQWIX3LMV43ASLTON2WKOZTGA2DEOBQGUYDGNI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
It doesn't work with the |
@comhon-project the issue is not reproducing in version 8, but it reproduces also in version 9. \Illuminate\Validation\Factory::$excludeUnvalidatedArrayKeys // v 9
/**
* Indicates that unvalidated array keys should be excluded, even if the parent array was validated.
*
* @var bool
*/
protected $excludeUnvalidatedArrayKeys = true;
//=> array:0 []
// v 8
/**
* Indicates that unvalidated array keys should be excluded, even if the parent array was validated.
*
* @var bool
*/
protected $excludeUnvalidatedArrayKeys;
//=> array:1 [
// "foo" => []
//] If we edit the V9 to be like V8 in vendor, then the behavior is the same as in 8. You can call this \Illuminate\Validation\Factory::includeUnvalidatedArrayKeys to fix the behaviour before \Illuminate\Validation\Factory::make is called /**
* Indicate that unvalidated array keys should be included in validated data when the parent array is validated.
*
* @return void
*/
public function includeUnvalidatedArrayKeys()
{
$this->excludeUnvalidatedArrayKeys = false;
} Example of custom validator: $this->app->singleton('validator', function ($app) {
$validator = new Factory($app['translator'], $app);
$validator->includeUnvalidatedArrayKeys(); // add this here
$validator->resolver( This is just an example. Maybe others could point out other simpler ways. Update: Acc to this: https://stackoverflow.com/a/76450468 // In a service provider
\Illuminate\Support\Facades\Validator::includeUnvalidatedArrayKeys(); |
<
8000
p dir="auto">thanks for that work around but i don't want to include the array key when it is invalid.
in my exemple : $validated = Validator::validate(['foo' => []], [
'foo' => 'present|array',
'foo.bar' => 'integer'
]); the nested value |
@comhon-project this is the code that removes the foo element if ($this->excludeUnvalidatedArrayKeys &&
in_array('array', $rules) &&
! empty(preg_grep('/^'.preg_quote($key, '/').'\.+/', array_keys($this->getRules())))) {
continue;
} |
maybe there should be an additional condition ? something like : if (
$this->excludeUnvalidatedArrayKeys &&
(in_array('array', $rules) || in_array('list', $rules)) &&
$value !== null &&
$value !== [] && // <= the new condition
! empty(preg_grep('/^' . preg_quote($key, '/') . '\.+/', array_keys($this->getRules())))
) {
continue;
} this way an empty array, that just don't have "maching" values, would be added to validated values. |
@comhon-project if excludeUnvalidatedArrayKeys * What do you think? Update $validated = Validator::validate(['foo' => ['x' => 0]], [
'foo' => 'present|array',
'foo.bar' => 'integer',
]); returns []; // but this is another issue, just like this one that you rose, even without your extra condition. |
If I'm not wrong, these cases will not passe the validation and an exception will be thrown earlier, just few lines before : throw_if($this->messages->isNotEmpty(), $this->exception, $this); so no need to double check in the if statement.
Bummer 😅 |
Laravel Version
11.44.2
PHP Version
8.3
Database Driver & Version
No response
Description
Hello everyone,
I've noticed an unexpected behavior when validating empty arrays with nested rules.
Here’s an example without any nested rules, which works as expected:
However, when I add a nested rule:
Expected:
the validated values should be the same and contain the "foo" key, since "foo.bar" is not required.
Steps To Reproduce
The text was updated successfully, but these errors were encountered: