Laravel validator does not keep numeric indexes on validation rules.
$validator = Validator::make(['c0'=>false,'c1'=>true], ['c0'=>'false']);
$this->assertTrue($validator->passes());
$validator = Validator::make(['c0'=>false,'c1'=>true], ['c1'=>'true']);
$this->assertTrue($validator->passes());
$validator = Validator::make([0=>false,1=>true], [0=>'false']);
$this->assertTrue($validator->passes());
$validator = Validator::make([0=>false,1=>true], [0=>'false', 1=>'true']);
$this->assertTrue($validator->passes());
$validator = Validator::make([0=>false,1=>true], [1=>'true']);
$this->assertTrue($validator->passes());// this fails
https://github.com/illuminate/validation/blob/master/Validator.php#L807
array_merge_recursive does keep associative array keys only for string keys, and not for numeric keys.
You must be specifying the key as a string (which also wouldn't work):
$validator = Validator::make([0 => false, 1 => true ], [ '1' => 'true']);
It first fails on array creation, as PHP casts string(1) into int(1) when setting the index on the array. After that, array_merge_recursive basically pushes the numeric indexes.
If array get supported a syntax like items.[index] (in this case just [1]), it could work. (Making the method less efficient as a result of extra logic.)
@tillkruss the issue is not resolved. Why did it got closed?
@lintaba: Is @balintant answer not sufficient?
No. He just aggrees that it exists, and reasons why.
Can you please share a real-life example? I don't seem to understand what this is about.
I'm trying to set up a validation where the input is not a regular form, but an array. (generated input)
The applied validation is also generated (from db)
Real life example: using this validation to import large csv files with lots of columns and rows, with validation/feedback for the columns.
To keep things simple, I don't want to use names on them. Therefore a simple numeric-indexed array would be the data, and also the validation rules:
$rules = ["rule0", "rule1", "rule2"];//generated
foreach(getData() as $data){
$validator = Validator::make($data, $rules);
}
I'm generating the ruleset once, and then have a lot of data rows and colls. To optimize it a bit, I'm trying to remove the empty rules. Therefore the array becomes jagged. (eg. rule1 is not neeeded):
$rules = [0=>"rule0", 2=>"rule2"];
and here is the issue. Laravel interprets the $rules above in the following way:
[0=>"rule0", 1=>"rule2] (or simply ["rule0", "rule2"] )
just simply reorganizes the array.
Actually, ["rule0", "rule1", "rule2"] aren't valid rules! I don't understand what you want really.
Because in that case I'd mess up the validation, and not Laravel ^^
so the problem is something like if Laravel would silently apply array_values on the rules.
Maybe its only me, but I think the failure of the following snippet is counter-intuitive:
$validator = Validator::make([0=>false,1=>true], [1=>'true']);
$this->assertTrue($validator->passes()); // this fails
What is true? There's no validation rule named true!
maybe our custom extension; checks if input evaluates to true. Here is a more canon example, this also fails:
$validator = Validator::make([ '0', '1' ], [1=>'in:1']);
$this->assertTrue($validator->passes()); // this also fails
So you're wanting to reference parameters being passed in by just an ID, rather than a key name?
Are you able to wrap all of your data in a key like params or something? Then you could do:
$validator = Validator::make([
'params.*' => ['in:1'],
])
But this implies all of the values would need to pass the same rules.
Im able to wrap them, but they need different rules. So this wouldn鈥檛 solve the problem.
I guess the * was just an example of the usual usage. You could replace it with the index.
Validator::make(
[
'params' => [
0 => 'foo',
2 => 'bar',
]
],
[
'params.0' => 'boolean',
'params.2' => 'integer',
'params.3' => 'required'
]
)
->messages()
->toArray()
// => [
// "params.0" => [
// "The params.0 field must be either true or false.",
// ],
// "params.2" => [
// "The params.2 field must be an integer.",
// ],
// "params.3" => [
// "The params.3 field is required.",
// ],
// ]
I don't see this as something crucial for the Laravel core to support - very uncommon use case for someone to use validation on a non-associative array.
I understand you're trying to simplify things by not using an associative array for each row's data. Is that really helping, though? Aside from dealing with this issue, how do you handle error messages - telling the user which column failed?
Also, depending on how you're trying to remove empty rules, have you considered the nullable rule to skip validating null values? Might be a use case.
Because there are so many different directions you could go, many of which adapt your data to the Validator's normal functionality, I wouldn't recommend a change to Laravel.
I fail to see the use case for this, sorry. It's best to post this idea at the laravel/ideas repository to get support for your idea if you still want to see it implemented.
Most helpful comment
I'm trying to set up a validation where the input is not a regular form, but an array. (generated input)
The applied validation is also generated (from db)
Real life example: using this validation to import large csv files with lots of columns and rows, with validation/feedback for the columns.
To keep things simple, I don't want to use names on them. Therefore a simple numeric-indexed array would be the data, and also the validation rules:
I'm generating the ruleset once, and then have a lot of data rows and colls. To optimize it a bit, I'm trying to remove the empty rules. Therefore the array becomes jagged. (eg. rule1 is not neeeded):
and here is the issue. Laravel interprets the
$rulesabove in the following way:just simply reorganizes the array.