Валидация массива полей

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Валидация массива полей

Сообщение megl »

В одной форме html существует несколько полей с именами: field[1], field[2]...

В модели прописано:

Код: Выделить всё

public $field = [];

public function rules()
    {
        return [
            /* ... */
            ['field', 'each', 'rule' => ['number','max'=>999.999,'min'=>-999.999]],
        ];
    } 
Далее внутри метода модели:

Код: Выделить всё

if (!$this->validate()) {
            return $this->addError('field', $this->errors);
        } 
Я не могу просто сделать save(), т.к. эти поля с одной страницы нужно преобразовать и уложить в несколько строк базы данных. Но валидацию как-то проходить нужно.

При такой постановке кода выделяются все поля field с пометкой одинаковой ошибки. Как сделать так, чтобы каждое поле отзывалось лишь на свою ошибку?

Если я вставляю индекс в addError('field[1]', $this->errors), это поле всё равно не выделяется. Да я и не знаю, как узнать, в каком из полей массива ошибка.
Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Валидация массива полей

Сообщение Ale}{ »

Я правильно понял - что field[1], field[2] - записываются в другую таблицу, и являются по сути другой сущности, и имеют эти сущности привязку к основной модели? Если да, то получаем - сохранение связанных сущностей - это нужно делать по другому и в транзакции
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Таблица в db:
id, pr_id, pat_id, num
где второе и третье - foreign keys, связь с другими таблицами
field[1] запишется в num в строку, где pr_id==1
field[2] запишется в num в строку, где pr_id==2
Я не буду нагружать, что такое pat_id, но оно тоже есть ))
Поэтому вопрос задал максимально коротко, чтобы не грузить всем весом проблемы. Задачу мне поставили сделать именно так.
Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Валидация массива полей

Сообщение Ale}{ »

смотри в сторону метода модели validateMultiple() - это на мой взгляд правильный подход,

если тебе нужно по заданию сделать только через each валидацию - то по быстрому приходит завязаться на выброс в сообщении {value} - оно покажет какой значение невалидное, - отсюда по значению искать индекс в массиве.
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Суть именно такая, что форма содержит абсолютно все строки из таблицы db, привязанные к 2 параметрам 2 других таблиц.
Грубо - привязаны к юзеру и ещё одному параметру.
Из всех этих строк берётся по одному полю (столбцу) и преобразовывается массив из 4 моделей для 4 форм (на одной странице).
Потому и получается одно поле, являющееся массивом: field[]
Когда делается ошибка - выделяются все поля той формы, что только что редактировалась.
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Отдельное поле имеет вид:

Код: Выделить всё

<input id="patientnum-field-1" class="form-control" type="text" value="12.000" name="PatientNum[field][1]">
"PatientNum[field][1]" - это деятельность YII2 (по названию модели), хотя я вписал просто field[1]


Если я добавляю ошибки вручную, ни один из вариантов не работает:

Код: Выделить всё

$this->addErrors(['field[1]'=>'ошибка 1','field[2]'=>'ошибка2']);

$this->addErrors(['field-1'=>'ошибка 1','field-2'=>'ошибка2']);

$this->addErrors(['patientnum-field-1'=>'ошибка 1','patientnum-field-2'=>'ошибка2']);

$this->addErrors(['PatientNum[field][1]'=>'ошибка 1','PatientNum[field][2]'=>'ошибка2']);
Данные об ошибках (если сделать во вьюхе var_dump($this->errors)) приходят.


Работает лишь

Код: Выделить всё

$this->addErrors(['field'=>'ошибка 1']);
но он обозначает ошибками весь массив полей.


Как обратиться к каждой ошибке в addErrors, чтобы каждая стояла на своём месте, а не под всеми соседями сразу?
Прочёл у создателей, что "вручную это делается легко", поэтому в ядро нет смысла такое вставлять ))

Какой правильный вариант названия поля в addErrors в моём случае?

Код: Выделить всё

$this->addErrors(['поле'=>'ошибка', 'поле'=>'ошибка']);
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Валидация массива полей

Сообщение ElisDN »

Перепишите в модели __get и __set, чтобы они превращали элементы массива field[5] в псевдополя field_5. А массив тогда исключите из rules и вручную в beforeValidate проверяйте.
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Эта мысль ещё пару дней назад посетила.
О замене массива рядом переменных.
Но неужели как-то изящнее нельзя?

Псевдополя - это что?

Да и если я в одной модели при приёме заменю массив на ряд переменных, как мне всё равно обращаться к addErrors?
Или вы имели в виду заменять массив на ряд переменных везде?
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Валидация массива полей

Сообщение ElisDN »

Да, везде. addError('field_' . $i, '...').
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Фу как некрасиво.
Ожидал от YII2 больших силы и гибкости.
Использовать вмест омассива ряд переменных, потому что YII2 не справляется.
Жуть.

А public field_1, public field_2 как объявлять? ))
Вечер перестаёт быть томным.
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Валидация массива полей

Сообщение ElisDN »

Не надо никаких public. Магические методы переопределите.
megl
Сообщения: 29
Зарегистрирован: 2015.10.05, 11:42

Re: Валидация массива полей

Сообщение megl »

Спасибо за помощь. Сделал.
Но осталось ощущение чего-то несуразного.
Из-за отсутствия поддержки массивов полей в YII2.
faeton
Сообщения: 88
Зарегистрирован: 2011.06.06, 01:00

Re: Валидация массива полей

Сообщение faeton »

У меня в таком массиве поля с разными именами, после переработки в config_item1, config_item2... они просто режуться фреймворком не доходя до магического сеттера. Странно, что этого нет в ядре
Изображение
Аватара пользователя
magicoder
Сообщения: 133
Зарегистрирован: 2015.12.16, 23:33
Контактная информация:

Re: Валидация массива полей

Сообщение magicoder »

Тема старая, но все же... Подскажите ,как удалось решить проблему.
Разработка на yii2 или чистом php.| email: site4coder@gmail.com | skype: for-web1
ZubkovAnton
Сообщения: 1
Зарегистрирован: 2021.05.04, 18:00

Re: Валидация массива полей

Сообщение ZubkovAnton »

На случай если кто то до сих пор не знает, проверено на 2.0.41.1 ActiveRecord
Для массива полей foo[bar] foo[bar][1][name] (любая вложенность)
В rules добавляем правило:

Код: Выделить всё

 ['foo', 'validateFooArray', 'skipOnEmpty' => false, 'skipOnError' => false] 
Добавляем функцию кастомного валидатора:

Код: Выделить всё

 public function validateFooArray($attribute, $params, $validator)
 {
 	// Ваши проверки
 	// В случае если в вашем массиве один из элементов не прошел проверку добавляем сообщение об ошибке
 	
       	$this->addError($attribute.'[bar]',$error); // $this->addError('foo[bar]',$error);
       	$this->addError($attribute.'[bar][1][name]',$error); // $this->addError('foo[bar][1][name]',$error);
 }
У меня еще стоит дополнительный обработчик в JS на события afterValidate и beforeSubmit но не для этого конкретного случая(наименования атрибутов я там никак не обрабатываю сразу отдаю в $yiiform.yiiActiveForm('add',[]))
Если без них у вас работать не будет выложу дополнительно
Аватара пользователя
tomclancys
Сообщения: 3
Зарегистрирован: 2020.06.05, 07:07

Re: Валидация массива полей

Сообщение tomclancys »

ZubkovAnton писал(а): 2021.05.04, 18:12 На случай если кто то до сих пор не знает, проверено на 2.0.41.1 ActiveRecord
Для массива полей foo[bar] foo[bar][1][name] (любая вложенность)
Покажите рабочий пример если не сложно. Ваш у меня не заработал на последний версии Yii2.
Ответить