Как организовать валидацию и сохранение динамических форм в YII?
Добрый день столкнулся с проблемой, с сохранением и вальвацией динамически полей.
Допустим для примера есть основная таблица в базе данных в ней есть некоторые параметры.
Клиент
- Ф.И.О
- Телефон
- Адрес проживания
- Возраст
- Пол
Хотелось бы добавить возможность для данной таблицы динамический добавлять разные типы полей, допустим поле - "подписан клиента на рассылку" да/нет или какой вид услуг предпочитает клиент ( выпадающий список с выбором нескольких услуг)
Это очень хорошо реализована в joomla 3 когда к материалам можно создать отдельные поля определенного типа с определённым набором данных и они будут применены ко всем материалам.
Я примерно набросал структуру базы данных
entity
-id
-somefield1
-somefield2
-somefield2
...
attribute
- id
- name // название поля
- type // тип поля
- default // значение по умолчанию
- required // обязательное
- params // здесь храним все наши параметры в зависимости от типа поля, допусти если нам нужен выпадающий список то храним что то типо options => [ option1 => [ name => параметр 1, value => 1], option1 => [ name => параметр 2, value => 2]
attribute_value
- attribute_id // ID поля
- entity_id // Модель
- value // значение
Теперь уже ближе, к сути, я ни как не могу разобраться как в activeform написать валидацию и сохранение entity и дополнительных параметров.
То есть что бы в форме вывести все поля модели entity и там же вывести все дополнительные поля созданные динамический. А при сохранении всё это чудо провалидировать.
1. Читаете из базы данные и формируете из них массив параметров который необходимо заполнить
2. На основе этого массива формируете динамическую модель
3. Динамическую модель скармливаете ActiveForm
С этим я примерно разобрался, делаю выборку из базы данных полей, после чего перебираю их и формирую массив атрибутов для динамической модели.
Затем добавляю правила вальвации в динамическую модель, после чего всё это скармливаю ActiveForm где опять же перебегаю массив полей.
В принципе всё чудесно работает. Форма загружается, валидируется.
После вальвации перебираю снова массив с параметрами, выбираю параметры из модели. И сохраняю значения. Но если честно мне кажется что это просто набор очень громоздкого бесмысленного кода. Может это можно сделать как то более изящно ?
#model основная модель
#dynamicModel - динамичная модель
#fields - набор параметров
//Загружаю данные из модели
if( $model->load(Yii::$app->request->post()) && $dynamicModel->load(Yii::$app->request->post()) {
//Проводим валидацию моделей
if($model->validate() && $dynamicModel->validate()){
//Сохраняю основную модель
$model->save();
//Перебираю массив полей
foreach ($fields as $field) {
//Проверяю содержит ли поле массив
if(is_array($dynamicModel->{$field->name})){
//Перебираю все значения значения
foreach ($dynamicModel->{$field->name} as $_value)
{
$value = new FieldValue();
$value->field_id = $field->id;
$value->model_id = $model->id;
$value->option_id = $_value;
$value->save();
}
} else {
//Иначе просто сохраняем значение не перебирая данные
$value = new FieldValue();
$value->field_id = $field->id;
$value->model_id = $model->id;
$value->option_id = $dynamicModel->{$field->name};
$value->save();
}
}
}
}
Просто, мне крайней не нравиться этот вариант, хоть он и работает вполне сносно, просто пугает, какой код получиться при обновлении данной модели.
Я просто не представляю как в будущем при обновлении параметров не запутаться в них, и не продублировать при сохранении.