3

I have table which have multiple reference to ohter tables like

user
id         name         email
categories
id         title
user_categories
user_id    category_id

Here a user will have multiple category associated with him/her

I am able to save these successfully with new records like following

View File:

echo $form->field($package_categories, 'category_id')->dropDownList( ArrayHelper::map(
StudyMaterialCategories::find()->all(), 'id', 'title'), 
['multiple' => true]
);

Save New record:

$model = new Packages();
$package_categories = new PackageCategories();
$request = Yii::$app->request;
if ($request->isPost) {
    $transaction = Yii::$app->db->beginTransaction();
    try {
        $post = $request->post();
        $model->load($post);
        $model->save();
        foreach ($post['PackageCategories']['category_id'] as $key => $value) {
            $package_categories = new PackageCategories();
            $package_categories->category_id = $value;
            $package_categories->package_id = $model->id;
            $package_categories->save();
        }
        $transaction->commit();
        return $this->redirect(['view', 'id' => $model->id]);
    } catch (Exception $ex) {
        $transaction->rolback();
        Yii::$app->session->setFlash("error", $ex->getMessage());
    }
}

Till now It's running successfully.

But I'm stuck when going to update the table. The problem part is dropdown list. How to set multiple selected option as per database if I'm coming with array of object. Have a look on the following code

$package_categories = PackageCategories::find()
->where('package_id=:package_id', ['package_id' => $id])->all();
if (count($package_categories) < 1) {
    $package_categories = new PackageCategories();
}
$request = Yii::$app->request;
if ($request->isPost) {
    $transaction = Yii::$app->db->beginTransaction();
    try {
        $post = $request->post();
        $model->load($post);
        $model->save();
        $package_categories = new PackageCategories();
        $package_categories->deleteAll(
            "package_id=:package_id", 
            [':package_id' => $model->id]
        );
        foreach ($post['PackageCategories']['category_id'] as $key => $value) {
            $package_categories = new PackageCategories();
            $package_categories->category_id = $value;
            $package_categories->package_id = $model->id;
            $package_categories->save();
        }
        $transaction->commit();
        return $this->redirect(['view', 'id' => $model->id]);
    } catch (Exception $ex) {
        $transaction->rolback();
        Yii::$app->session->setFlash("error", $ex->getMessage());
    }
}

if I try to get first object of the array $package_categories of only able to set selected one option

1
  • to show multiple items selected inside a multi-select you just need to set the values as array to the model field that is used to show the multiple select. Commented Feb 3, 2018 at 21:12

1 Answer 1

3

This is an example code of a model class Permit which has a many to many relationship with Activity through PermitActivity (pivot table model).

Model Class Activity

public class Permit extends \yii\db\ActiveRecord {
    public $activities_ids;
    ...
    public function rules() {
        return [
            ...
            [['activities_ids'], 'safe'],
            ...
        ];
    }
    ...
    // Method called after record is saved, be it insert or update.
    public function afterSave($insert, $changedAttributes) {
        // If this is not a new record, unlink all records related through relationship 'activities'
        if(!$this->isNewRecord) {
            // We unlink all related records from the 'activities' relationship.
            $this->unlinkAll('activities', true);
            // NOTE: because this is a many to many relationship, we send 'true' as second parameter
            // so the records in the pivot table are deleted. However on a one to many relationship
            // if we send true, this method will delete the records on the related table. Because of this,
            // send false on one to many relationships if you don't want the related records deleted.
        }

        foreach($this->activities_ids as $activity_id) {
            // Find and link every model from the array of ids we got from the user.
            $activity = Activity::findOne($activity_id);
            $this->link('activities', $activity);
        }

        parent::afterSave($insert, $changedAttributes);
    }
    ...
    // Declare relationship with Activity through the pivot table permitActivity
    public function getActivities(){
        return $this->hasMany(Activitiy::className(), ['id' => 'activity_id'])
            ->viaTable('permitActivity',['permit_id' => 'id']);
    }
    ...
    public function afterFind(){
        parent::afterFind();
        $this->activities_id = ArrayHelper::getColumn($this->activities, 'id');
    }
}

This way the model class is the one responsible for creating and updating the relationship using the pivot table.

The most important thing is to have the relationship method declared correctly.

Edit

This is an example of the view using kartikv\widgets\Select2. I don't really know if dropDownList supports multiple select, however Select2 has so many useful features i usually use it over other options.

echo $form->field($model, 'activities')->widget(Select2::classname(), [
    'data' => $data,
    'options' => [
        'placeholder' => '...'
    ],
    'pluginOptions' => [
        'allowClear' => true,
        'multiple' => true,
    ],
]);
Sign up to request clarification or add additional context in comments.

8 Comments

My question is how do I will set multiple item selected in view
In my example, the multiple items field is activities_ids
Give me an example to show on view like $form->field($modal_obj, 'attribute_name')->dropdownlist($items, ['multiple'=>true])
Added example with Select2 widget by Krajee
I think $data variable in the widget is array, but my question is how do I will set two options as selected when we are in update form?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.