skip to Main Content

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

3

Answers


  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],
    
    Login or Signup to reply.
  2. 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 AppRules directory.

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

      use AppRulesNestedArrayWithStrings;
      
    • 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 AppRules;
    
    use IlluminateContractsValidationRule;
    
    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.

    Login or Signup to reply.
  3. 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!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search