0

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"
  ]
0

3 Answers 3

1

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!

Sign up to request clarification or add additional context in comments.

Comments

1

Create custom rule class. For ex: NestedArrayWithStrings

then check:

if (is_array($item))

in a for loop etc.

add to validation like this:

'answers' => ['required', 'array', new NestedArrayWithStrings],

Comments

1

You would need to define a custom rule in Laravel for this.

  • Run the command php artisan make:rule NestedArrayWithStrings and this will create a new file in App\Rules directory.

  • To add this rule, first import the rule class namespace in your controller.

    use App\Rules\NestedArrayWithStrings;
    
  • Now, use it in your validator as:

$v = Validator::make($request->all(),[
        'answers' => [
            'required',
            'array',
            new NestedArrayWithStrings
        ]
    ]);

if($v->fails()){
    echo $v->errors()->first(); // or similar
}

Below will be your recursive code to judge the values and if it passes:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class NestedArrayWithStrings implements Rule{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value){
        if(!is_array($value)) return false;
        foreach($value as $v){
            if(is_array($v)){
               if(!$this->passes($attribute, $v)){
                 return false;
               }
            }else if(!is_string($v)){
                return false;
            }
        }

        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message(){
        return 'Answers can only contain arrays filled with strings.';
    }
}

Note: Technically, everything given from the frontend will come as a string, so you will need to add additional checks along with is_string to filter out the kind of data you wish to have.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.