単一のフォームで同じ種類の複数のモデルを処理する必要がある場合があります。たとえば、各設定が名前と値のペアとして格納され、Setting
アクティブレコード モデルで表現される複数の設定などです。この種のフォームは、「表形式入力」とも呼ばれます。これに対して、異なる種類の異なるモデルを処理する方法は、「複数のモデルを持つ複雑なフォーム」のセクションで説明されています。
以下に、Yii で表形式入力を実装する方法を示します。
対処する必要のある状況は3つあり、それぞれ少しずつ異なる方法で処理する必要があります。
以前に説明した単一モデルのフォームとは対照的に、ここではモデルの配列を扱っています。この配列は、テーブルのようなスタイルで各モデルの入力フィールドを表示するためにビューに渡され、一度に複数のモデルのロードと検証を可能にする yii\base\Model のヘルパーメソッドを使用します。
まず、コントローラのアクションから始めましょう。
<?php
namespace app\controllers;
use yii\web\Controller;
use app\models\Setting;
class SettingsController extends Controller
{
// ...
public function actionUpdate()
{
$settings = Setting::find()->indexBy('id')->all();
if ($this->request->isPost) {
if (Setting::loadMultiple($settings, $this->request->post()) && Setting::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()
を使用して、save() に false
をパラメータとして渡して、検証を二度実行しないようにします。
次に、update
ビューにあるフォームです。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$form = ActiveForm::begin();
foreach ($settings as $id => $setting) {
echo $form->field($setting, "[$id]value")->label($setting->name);
}
echo Html::submitButton('Save');
ActiveForm::end();
ここでは、各設定に対して名前と値を持つ入力欄をレンダリングしています。Model::loadMultiple() がどのモデルにどの値を入力するかを判断する方法であるため、入力名のインデックスを適切に追加することが重要です。
新しいレコードの作成は、モデルをインスタンス化する部分を除いて、更新と似ています。
public function actionCreate()
{
$settings = [];
if ($this->request->isPost) {
$count = count($this->request->post($setting->tableName()));
for ($i = 0; $i < $count; $i++) {
$settings[$i] = new Setting();
}
if (Setting::loadMultiple($settings, $this->request->post()) && Setting::validateMultiple($settings)) {
foreach ($settings as $setting) {
$setting->save(false);
}
return $this->redirect('index');
}
}
$settings[] = new Setting();
return $this->render('create', ['settings' => $settings]);
}
ここでは、ビューに常に少なくとも1つのテキストフィールドが表示されるように、デフォルトで1つのモデルを含む初期の $settings
配列を作成します。さらに、受け取った可能性のある入力行ごとに追加のモデルを追加します。
ビューでは、JavaScriptを使用して新しい入力行を動的に追加できます。
注:このセクションは開発中です。
まだコンテンツはありません。
TBD(後日追記)
タイプミスを見つけたり、このページを改善する必要があると思われますか?
githubで編集してください !
ここには、試してみる気にさせてくれた完全なマスター/詳細がありました。親モデルと子モデルを含むフォームの Ajax 検証リクエストを受け取るときに、コントローラで実行する必要がある重要な詳細があります。
ケース; 'Docbotellas' という名前の親クラスのモデルと、クラス名が 'Detdocbotellas' である子モデルのグループがあります。 'Detdocbotellas' のリンクフィールドは 'doc_id' です。表形式入力を収集してみます。
コントローラ内
ビュー内
<?php $form =\yii\bootstrap\ActiveForm::begin([ 'enableAjaxValidation'=> true,'id'=>'tabular-botellas' ]); ?> <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12"> <?= $form->field($model, 'number')->textInput() ?> </div> <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12"> <?= $form->field($model, 'weight')->textInput(['maxlength' => true]) ? </div> <label for="items" class="control-label">Items</label> <div class="table-responsive"> <table class="table table-bordered" id="items"> <thead> <tr style="background-color: #ddd;"> <th width="5%" class="text-center">Acciones</th> <th width="15%" class="text-left">Code</th> <th width="80%" class="text-left">Description</th> </tr> </thead> <tbody> <?php $orden=0; foreach($items as $item){ ?> <?php echo $this->render('item', ['form'=>$form,'item'=>$item,'orden'=>$orden]); $orden+=1; ?> <?php } ?> <tr id="addItem"> <td class="text-center"><button type="button" id="button-add-item" data-toggle="tooltip" title="Añadir" class="btn btn-xs btn-primary" data-original-title="Añadir"><i class="fa fa-plus"></i></button></td> <td class="text-right" colspan="2"></td> </tr> </tbody> </table> </div> <div class="form-group"> <?= Html::submitButton(Yii::t('names.labels', 'Save'), ['class' => 'btn btn-success']) ?> </div> <?php \yii\bootstrap\ActiveForm::end(); ?> </div>
ビュー 'item'
<?= $form->field($item,"[$orden]codigo")->label(false);?> <?= $form->field($item,"[$orden]descripcion")->label(false); ?> <?= $form->field($item, "[$orden]id")->hiddenInput(['value' => $item->id])->label(false);?>コメントするには、サインアップまたはログインしてください。