Laravel表单验证 - 输入数组的MessageBag中没有数组索引


Laravel form validation - no array index in MessageBag for input array

我有一个表单,它有一个输入"数组",提交时,使用Laravel的验证器进行验证。

验证按预期工作,将规则应用于每个数组元素,并相应地返回错误的 MessageBag。

问题:MessageBag 不引用数组的相关索引。有没有办法(除了为数组的每个可能的索引定义规则)让Laravel引用相关的输入数组索引?

示例网页

<input name="something[]" type="text" />
<input name="something[]" type="text" />
<input name="something[]" type="text" />
...

样品验证器

Validator::make
(
    Input::all(),
    array
    (
        "something" => array("required", "exists:somewhere")
    )
);

验证后的示例消息包(不引用输入数组索引)

object(Illuminate'Support'MessageBag)#150 (2)
{
    ["messages":protected]=> array(6)
    {
        ["something"]=> array(1)
        {
            [0]=> string(26) "Some error message"
        }
    }
    ...
}

我未能找到任何使用标准 Laravel 核心功能执行此操作的方法,因此我最终扩展了 Validator 类以实现解决方案。

为了更好地理解此解决方案,记录了下面的代码。

  1. 创建app/libraries/MyApp/Validation目录以保存新类

  2. 本文的扩展'Illuminate'Validation'Validator("从类解析"方法):扩展Laravel 4验证器

  3. 覆盖Validator#passes()

    namespace MyApp'Validation;
    use 'Illuminate'Validation'Validator;
    class ArrayAwareValidator extends Validator
    {
        //Override Validator#passes() method
        public function passes()
        {
            //For each validation rule...
            foreach ($this->rules as $attribute => $rules)
            {
                //Get the value to be validated by this rule
                $values = $this->getValue($attribute);
                //If the value is an array, we got an HTML input array in our hands
                if(is_array($values))
                {
                    //Iterate through the values of this array...
                    for($i=0; $i<count($values); $i++)
                    {
                        //...and create a specific validation rule for this array index
                        $this->rules[$attribute.".".$i] = $rules;
                    }
                    //Delete original rule
                    unset($this->rules[$attribute]);
                }
            }
            //Let Validator do the rest of the work
            return parent::passes();
        }
    }
    
  4. 这将导致以下MessageBag

    object(Illuminate'Support'MessageBag)#151 (2)
    {
        ["messages":protected]=> array(2)
        {
            ["something.0"]=>
            array(1)
            {
              [0]=> string(26) "Some error message"
            }
            ["something.1"]=>
            array(1)
            {
              [0]=> string(26) "Some error message"
            }
        }
        ...
    }
    
  5. 在客户端,使用 JavaScript,我将名称从索引中拆分(例如"something.1"到"something"和"1"),然后使用此信息来识别正确的表单输入。我正在使用 Ajax 提交表单,因此您可能需要在此处使用不同的方法。

注意:这是一个务实的解决方案,非常适合我的问题。如您所见,数组索引与同一字符串中的输入名称一起传递。您可能希望进一步扩展内容,以便Validator返回具有名称和索引作为单独内容的对象或数组。

你的验证器应该是这样的:

       Validator::make
 (
   Input::all(),
array
(
    'something' => 'required,unique:somewhere'
));