Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
203 views
in Technique[技术] by (71.8m points)

Validation of array form fields in laravel 4 error

How can we validate form fields that are arrays? Take a look at the following code

UserPhone Model:

 public static $rules= array(
    'phonenumber'=>'required|numeric',
    'isPrimary'=>'in:0,1'
)
...........

UserController:

$validation = UserPhone::validate(Input::only('phonenumber')));


    if($validation->passes())
      {
         $allInputs = Input::only('phonenumber','tid');
         $loopSize = sizeOf($allInputs);

         for($i=0;$i<$loopSize;$i++)
         {

         $phone = UserPhone::find($allInputs['tid'][$i]);
         $phone->phonenumber = $allInputs['phonenumber'][$i];
         $phone->save();

        }

     return Redirect::to('myprofile')->with('message','Update OK');

  }
  else
  {
     return Redirect::to('editPhone')->withErrors($validation);

  } 

}

the $validation comes from a BaseModel which extends Eloquent.

In my view:

 <?php $counter=1; ?>
          @foreach($phones as $thephone)

           <section class="col col-12">
              <label class="label">Phone Number {{$counter++}}</label>
              <label class="input">
              <i class="icon-append icon-phone"></i>
                 {{Form::text('phonenumber[]',$thephone->phonenumber)}}
                 {{Form::hidden('tid[]',$thephone->id)}}
              </label>
            </section>
          @endforeach

Everything is working fine and I get all the phone numbers I want in the Update Form, but I cannot update the model because the validation fails with the message "Phonenumber must be a number".

I know that there is not a simple solution for validating array form fields and I tried to extend the validator class but with no success.

How can I validate this kind of fields?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's the solution I use:

Usage

Simply transform your usual rules by prefixing each. For example:

'names' => 'required|array|each:exists,users,name'

Note that the each rule assumes your field is an array, so don't forget to use the array rule before as shown here.

Error Messages

Error messages will be automatically calculated by the singular form (using Laravel's str_singular() helper) of your field. In the previous example, the attribute is name.

Nested Arrays

This method works out of the box with nested arrays of any depth in dot notation. For example, this works:

'members.names' => 'required|array|each:exists,users,name'

Again, the attribute used for error messages here will be name.

Custom Rules

This method supports any of your custom rules out of the box.

Implementation

1. Extend the validator class

class ExtendedValidator extends IlluminateValidationValidator {

    public function validateEach($attribute, $value, $parameters)
    {
        // Transform the each rule
        // For example, `each:exists,users,name` becomes `exists:users,name`
        $ruleName = array_shift($parameters);
        $rule = $ruleName.(count($parameters) > 0 ? ':'.implode(',', $parameters) : '');

        foreach ($value as $arrayKey => $arrayValue)
        {
            $this->validate($attribute.'.'.$arrayKey, $rule);
        }

        // Always return true, since the errors occur for individual elements.
        return true;
    }

    protected function getAttribute($attribute)
    {
        // Get the second to last segment in singular form for arrays.
        // For example, `group.names.0` becomes `name`.
        if (str_contains($attribute, '.'))
        {
            $segments = explode('.', $attribute);

            $attribute = str_singular($segments[count($segments) - 2]);
        }

        return parent::getAttribute($attribute);
    }
}

2. Register your validator extension

Anywhere in your usual bootstrap locations, add the following code:

Validator::resolver(function($translator, $data, $rules, $messages)
{
    return new ExtendedValidator($translator, $data, $rules, $messages);
});

And that's it! Enjoy!

Bonus: Size rules with arrays

As a comment pointed out, there's seems to be no easy way to validate array sizes. However, the Laravel documentation is lacking for size rules: it doesn't mention that it can count array elements. This means you're actually allowed to use size, min, max and between rules to count array elements.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...