Yii 1.1: Save or Update Multiple related model values in one Tabular input form

1 follower

In this wiki I will show you how to save/update a model with many related model For example: How to set a product to multiple categories only in one post form ?

Schema database table

Product:id,title,... Category:id,title,... product_to_category: id,productId,categoryId,...

You have to add the below code in your Model and View (Suppose you have already creates the default MVC for Product)

So,

Model:

//1)add validator to allow multiple values
 public function rules() {
        return array(
            ...
            array('toCat', 'type', 'type' => 'array', 'allowEmpty' => false),
            ...
        );
    }
 
 
//2)stored and inserted values
public $toCat = [];
public $toCat_stored = [];
 
//retrieve the related ids
public function afterFind() {
    $this->toCat_stored = [];
    foreach ($this->productsToCategories as $r) { //productsToCategories is relation with table product_to_category
        $this->toCat[] = $r->CategoryId;
    }
 
    $this->toCat_stored = $this->ItemToCat;
 
    parent::afterFind();
}
 
//3) save the selected categories, remove the unselected categories
protected function afterSave() {
 
        if (!$this->toCat) //if nothing selected set it as an empty array
            $this->ItemToCat = array();
 
        //save the new selected ids that are not exist in the stored ids
        $ids_to_insert = array_diff($this->toCat, $this->toCat_stored);
 
        foreach ($ids_to_insert as $nid) {
            $m = new ProductToCategory();
            $m->productId = $this->id;
            $m->CategoryId = $nid;
            $m->save();
        }
 
        //remove the stored ids that are not exist in the selected ids
        $ids_to_delete = array_diff($this->ItemToCat_stored, $this->ItemToCat);
 
 
        foreach ($ids_to_delete as $did) {
            if ($d = ProductToCategory::model()->findByAttributes(['productId' => $this->id, 'CategoryId' => $did])) {
                $d->delete();
            }
        }
 
        parent::afterSave();
}

Controller: nothing special, save model and render view as usually

View: (_form.php)

In your form widget add the below code before submit button

<div>
        <?php
        $allcats = CHtml::listData(Category::model()->findAll(),'id','title');
 
        echo '<table style="width:50%;"><thead><tr><th>category</th><th>checked</th></tr><thead><tbody>';
        foreach ($allcats as $catId => $catTitle) :
            $isChecked = in_array($catId, $model->toCat);
            echo '<tr>';
            echo '<td>' . $catTitle . '</td>';
            echo '<td>' . CHtml::checkBox('Product[toCat][]', $isChecked, array('value' => $catId)) . '</td>';
            echo '</tr>';
        endforeach;
        echo '</tbody></table>';
        ?>
    </div>

Enjoy it!

Total 2 comments

#17327 report it
langy at 2014/05/24 06:58am
Please merge

+1 for richard's comment, here is another wiki that discusses same, please merge so we do not have duplicate wikis.

#17326 report it
Richard M at 2014/05/24 06:55am
Duplicate

This is already discussed in a few earlier wikis. You may want to remove and merge.

For Yii 1.x here, and other wikis as well.

For Yii 2.x here

Leave a comment

Please to leave your comment.

Write new article