phplaravelvalidationlaravel-validationlaravel-10

Laravel 10 - validation rule "string or array"


I need to add validation for a dynamic array whose elements can be strings or subsequent arrays containing strings, but I can't find a way to save this rule.

My current validation:

        $data = $request->validate([
            'answers' => ['required', 'array'],
            'answers.*' => ['required', 'max:255'],
            'answers.*.*' => ['nullable', 'string', 'max:255']
        ]);

Sample input:

  "answers" => array:3 [▼
    4 => array:1 [▼
      0 => "Tests"
      1 => "Tests 2"
    ]
    5 => "Test"
    6 => "Yes"
  ]

Solution

  • So, I created something that might solve your problem, I've tried it and works.

    First you might want to create a new Rule class, as I commented in your question, maybe using artisan command php artisan make:rule DynamicArray for example to give it a name.

    You'll need to do something like this inside app/Rules/DynamicArray:

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $this->checkArray($attribute, $value, $fail);
    }
    
    private function checkArray(string $attribute, mixed $value, Closure $fail): void
    {
        if(!is_array($value)){
            $fail("The $attribute must be an array.");
            return;
        }
    
        foreach ($value as $element){
            if (is_array($element)) {
                $this->checkArray($attribute, $element, $fail);
            } else if (!is_string($element)) {
                $fail("The $attribute is invalid.");
                return;
            }
        }
    }
    

    then in your controller you'll end with this:

        $data = $request->validate([
            'answers' => ['required', 'array', new DynamicArray]
        ]);
    
        dd($data);
    

    you might debug $data to check if it's working:

        dd($data);
    

    It will pass the valildation:

    validation pass

    Hope that solve your problem!