Simple way to set related models in hasMany relations

Hi! This is a simple way to make a setter for hasMany relations. You could also extend \yii\db\ActiveRecord and add a setMany method in a similar way.

In model:

In the example below we have a model Employee with a hasMany relation with a model Branch.




class Employee extends ActiveRecord{

     

    //We need this to store temporarily the related models:

    private $_branches;


    /**

     * Set only the ids of each related model in "branches"

     * @inheritdoc

     */

    public function rules()

    {

        return [

            ...

            [['branches'],'safe'],

            ...

        ];

    }

    


    /**

     * Yii2 relational getter:

     * @return \yii\db\ActiveQuery

     */

    public function getBranches()

    {

        return $this->hasMany(Branch::className(), ['branch_id' => 'branch_id'])->viaTable('branch_has_employee', ['employee_id' => 'employee_id']);

    }

    

    /**

     * @param type $categories

     */

    public function setBranches($branches)

    {

        if(empty($branches)){

            $branches = [];

        }        

        $this->_branches = $branches;


        //This function will be called after insert or after update

        $saveBranches = function($event){

            //Remove existing relations

            $this->unlinkAll('branches', true);

            //Save new relations

            foreach ($this->_branches as $id){

                $this->link('branches', Branch::findOne($id));

            }

        };


        $this->on(self::EVENT_AFTER_INSERT, $saveBranches);

        $this->on(self::EVENT_AFTER_UPDATE, $saveBranches);

    }

}



Extending \yii\db\ActiveRecord with a setMany method is very easy too. In the example above, you should extend the model from your ActiveRecord implementation and declare a method setBranches($branches){ $this->setMany(‘branches’, $branches); }.

I hope you find this useful!