Иногда вам нужно обрабатывать несколько моделей одного типа в одной форме. Например, несколько настроек, где каждый параметр хранится как пара имя-значение и представлен моделью Setting активной записи. Этот вид формы также часто называют «табличным вводом».
Ниже показано, как реализовать табличный ввод с Yii. Есть три различные ситуации для покрытия, которые приходится решать несколько иначе:
- Обновление фиксированного набора записей из базы данных
- Создание динамического набора новых записей
- Обновление, создание и удаление записей на одной странице
В отличие от описанных ранее форм с одной моделью, сейчас мы работаем с множеством моделей. Этот массив передается в представление, чтобы отображать поля ввода для каждой модели в таблице, подобной стилю, и мы будем использовать вспомогательные методы yii\base\Model
, которые позволяют загружать и проверять сразу несколько моделей:
Model::loadMultiple()
загружает данные сообщения в массив моделей.Model::validateMultiple()
проверяет массив моделей.
Обновление фиксированного набора записей
Начнем с действия контроллера:
<?php
namespace app\controllers;
use Yii;
use yii\base\Model;
use yii\web\Controller;
use app\models\Setting;
class SettingsController extends Controller
{
// ...
public function actionUpdate()
{
$settings = Setting::find()->indexBy('id')->all();
if (Model::loadMultiple($settings, Yii::$app->request->post()) && Model::validateMultiple($settings)) {
foreach ($settings as $setting) {
$setting->save(false);
}
return $this->redirect('index');
}
return $this->render('update', ['settings' => $settings]);
}
}
В приведенном выше коде мы используем indexBy()
для извлечения моделей из базы данных для заполнения массива, индексированного первичными ключами моделей. Впоследствии они будут использоваться для определения полей формы. Model::loadMultiple() заполняет несколько моделей данными формы, поступающими из POST, и Model::validateMultiple()
проверяет все модели сразу. Поскольку мы проверили наши модели раньше, используя validateMultiple()
, мы теперь передаем false как параметр для save(), чтобы не запускать проверку дважды.
Теперь форму, которая находится в представлении update:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$form = ActiveForm::begin();
foreach ($settings as $index => $setting) {
echo $form->field($setting, "[$index]value")->label($setting->name);
}
ActiveForm::end();
Здесь для каждого параметра мы отображаем имя и вход со значением. Важно добавить правильный индекс для имени входа, поскольку именно так Model::loadMultiple() определяет, какую модель заполнить, с какими значениями.
Создание динамического набора новых записей
Создание новых записей аналогично обновлению, за исключением части, где мы создаем экземпляры моделей:
public function actionCreate()
{
$count = count(Yii::$app->request->post('Setting', []));
$settings = [new Setting()];
for($i = 1; $i < $count; $i++) {
$settings[] = new Setting();
}
// ...
}
Здесь мы создаем начальный массив $settings
, содержащий одну модель по умолчанию, так что в представлении всегда будет хотя бы одно текстовое поле. Кроме того, мы добавляем больше моделей для каждой строки ввода, которую мы, возможно, получили. В представлении вы можете использовать javascript для динамического добавления новых входных строк.
0 комментариев