Проверка формы Laravel — нет индекса массива в MessageBag для входного массива

У меня есть форма, которая имеет входной «массив», который при отправке проверяется с помощью Laravel’s Validator.

Проверка работает, как и ожидалось, применяя правило к каждому элементу массива и соответственно возвращая MessageBag с ошибками.

Проблема: MessageBag не ссылается на связанный индекс массива.
Есть ли способ (помимо определения правила для каждого возможного индекса массива) сделать так, чтобы Laravel ссылался на связанный индекс входного массива?

Образец HTML

<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")
)
);

Образец MessageBag после проверки (нет ссылки на индекс входного массива)

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

2

Решение

Я не смог найти какой-либо способ сделать это, используя стандартную функциональность ядра Laravel, поэтому в итоге я расширил Validator класс для реализации решения.

Код ниже документирован для лучшего понимания этого решения.

  1. созданный app/libraries/MyApp/Validation каталоги для проведения новых классов

  2. расширенный \Illuminate\Validation\Validator согласно этой статье (метод «Разрешить из класса»): Расширение валидатора Laravel 4

  3. Override 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, я разделяю имя из индекса (например, «что-то.1» на «что-то» и «1»), а затем использую эту информацию для определения правильного ввода формы. Я использую Ajax для отправки формы, поэтому вам может потребоваться использовать другой подход здесь.

Замечания: Это прагматичное решение, которое хорошо подходит для моей проблемы. Как видите, индекс массива передается вместе с именем входа в той же строке. Возможно, вы захотите расширить что-то еще, чтобы сделать Validator вернуть объект или массив с именем и индексом как отдельные вещи.

1

Другие решения

Ваш валидатор должен быть таким:

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

По вопросам рекламы [email protected]