ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Get only validated data when validating arrays

Open dsazup opened this issue 5 years ago • 6 comments

Hello,

I would like to discuss one of the issues that I often have when validating arrays. Let's say I have this validation:

return [
    'source' => 'required',
    'target' => 'required',
    'paths' => 'required|array',
    'paths.*.from' => 'required',
    'paths.*.to' => 'required',
];

If I then send this data:

{
    "source": "foo",
    "target": "bar"
    "paths": [
        {
            "id": 12345,
            "from": "/",
            "to": "/test"
        }
    ] 
}

And call $request->validated(), I expect to only get the data

array:3 [
  "source" => "foo"
  "target" => "bar"
  "paths" => array:1 [
    0 => array:3 [
      "from" => "/"
      "to" => "/test"
    ]
  ]
]

What I actually get is:

array:3 [
  "source" => "foo"
  "target" => "bar"
  "paths" => array:1 [
    0 => array:3 [
      "id" => "12345"
      "from" => "/"
      "to" => "/test"
    ]
  ]
]

Problem: Notice the paths[0].id. This prevents me from just doing $model->relation()->createMany($validated['paths']), because 'id' is not a field I expect to be in that array. This is only an issue if I have $guarded = [] on my model though, but I do have it on most of my models. I understand why this is there, because technically I validated the 'paths' attribute, so it just adds the whole thing to the validated array, and then also does paths..from, and paths..to.

Possible solution: I was having a look, at the validated method in the validator class, and looks like we could quickly fix this with modifying the check https://github.com/laravel/framework/blob/5.8/src/Illuminate/Validation/Validator.php#L341 here with if ($value !== $missingValue && ! $this->hasRule($key, ['Array'])) { which would mean that if it has an array rule, it would not set that specific field, and it would rely on validations like paths.*.from, paths.*.to.

This also means, that if we only validate that attribute to be an array, and we do not validate each child attribute, this would not work and it would not be in $validated array, which might not necessarily be what other people expect, but the way I work, this would be perfect.

The only other solution I can think of is to change how validated method works and do checks recursively on each array attribute..

I would like to get your opinion on this? Is this something worth changing?

dsazup avatar Jul 04 '19 10:07 dsazup

same problem

shakhzodkudratov avatar Jul 16 '20 14:07 shakhzodkudratov

I have this issue too, I'd like to use Model::create($request->validated()); but since I use MongoDB that could become a problem.

vacoup96 avatar Jul 22 '20 08:07 vacoup96

same issue here...

imdadturi avatar Sep 06 '20 07:09 imdadturi

same

gajosadrian avatar Apr 23 '21 11:04 gajosadrian

Dump.

LocalHeroPro avatar Jun 08 '21 20:06 LocalHeroPro

The problem is that validation explicitly says that we want the array so it's validated. The only real solution would be to have a rule which can explicitly exclude it from the validated data. Sadly currently the closest one is the exclude_if rule but that removes the whole array with all child elements.

netpok avatar Jun 09 '21 07:06 netpok