我有一个允许用户添加许多子记录的表单,在我的情况下,他们被称为" Items"。更新主记录时,用户可以添加,编辑或删除子记录。一切正常,但我正在寻找更好的方法来做到这一点。
目前,在我的Update操作中,我首先删除任何现有的子记录。然后我保存表格帖子中的所有子记录。
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
// first delete all existing child records
Item::deleteAll(['parent_id' => $model->id]);
// get the new set of posted Items
$items = Yii::$app->request->post('Item');
if (!empty($items) && is_array($items)) {
// save each Item
foreach ($items as $index => $values) {
$item = new Item();
$item->attributes = $values;
$item->parent_id = $model->id;
$item->save();
}
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
表单视图:
<form method="post" action="">
<?php foreach ($model->items as $index => $item): ?>
<?php echo Html::activeTextInput($item, "[$index]name"); ?>
<!-- Example output -->
<!-- <input id="item-0-name" name="Item[0][name]" value="Test" type="text"> -->
<a href="#">Remove this Item</a>
<?php endforeach; ?>
<button type="submit">Submit</button>
</form>
<a href="#">Add a new Item</a>
在上面$model->items
指的是父模型中的关系:
public function getItems()
{
return $this->hasMany(Item::className(), ['parent_id' => 'id']);
}
当用户点击&#34;添加新商品&#34;它只是使用JavaScript来克隆最后一项,并用下一个值替换它的索引。
通常,用户不会更改任何子记录。因此,在这种情况下删除和重新添加子记录的过程毫无意义。
我想知道的是,有没有办法可以智能地处理这个问题?例如:
答案 0 :(得分:2)
您可以使用indexBy()
按ID标识与索引相关项目的关系:
public function getItems() {
return $this->hasMany(Item::class, [/*...*/])->indexBy('id');
}
然后您可以检查具有此ID的记录是否已存在并执行更新/删除/创建操作:
// get the new set of posted Items
$items = Yii::$app->request->post('Item');
$existing = $model->items;
if (!empty($items) && is_array($items)) {
// save each Item
foreach ($items as $index => $values) {
if (!isset($existing[$index])) {
// create new item
$item = new Item();
$item->attributes = $values;
$item->parent_id = $model->id;
$item->save();
} else {
// update existing
$existing[$index]->attributes = $values;
$existing[$index]->save();
// remove from $existing array as already processed
unset($existing[$index]);
}
}
// right now $existing has only existing and not updated items - it means
// that they're not available in POST data so we should remove it
foreach ($existing as $item) {
$item->delete();
}
}