Retrieve data from junction table in Yii2

前端 未结 4 1210
离开以前
离开以前 2021-02-01 09:18

I\'m trying to get data from a join table in Yii2 without an additional query. I have 2 models (User, Group) associated via the junction table (user_group). In

4条回答
  •  礼貌的吻别
    2021-02-01 09:58

    I don't know for sure it is best solution. But for my project it will be good for now :)

    1) Left join

    Add new class attribute in User model public $flag;. Append two lines to your basic relation but don't remove viaTable this can (and should) stay.

    public function getUsers()
    {
        return $this->hasMany(User::className(), ['id' => 'user_id'])
            ->viaTable('user_group', ['group_id' => 'id'])
            ->leftJoin('user_group', '{{user}}.id=user_id')
            ->select('{{user}}.*, flag') //or all ->select('*');
    }
    

    leftJoin makes possible to select data from junction table and with select to customize your return columns. Remember that viaTable must stay because link() relies on it.

    2) sub-select query

    Add new class attribute in User model public $flag;

    And in Group model modified getUsers() relation:

    public function getUsers()
    {
        return $this->hasMany(User::className(), ['id' => 'user_id'])
            ->viaTable('user_group', ['group_id' => 'id'])
            ->select('*, (SELECT flag FROM user_group WHERE group_id='.$this->id.' AND user_id=user.id LIMIT 1) as flag');
    }
    

    As you can see i added sub-select for default select list. This select is for users not group model. Yes, i agree this is litle bit ugly but does the job.

    3) Condition relations

    Different option is to create one more relation for admins only:

    // Select all users
    public function getUsers() { .. }
    
    // Select only admins (users with specific flag )
    public function getAdmins()
    {
        return $this->hasMany(User::className(), ['id' => 'user_id'])
            ->viaTable('user_group', ['group_id' => 'id'],
            function($q){
                 return $q->andWhere([ 'flag' => 'ADMIN' ]); 
            });
    }
    

    $Group->admins - get users with specific admin flag. But this solution doesn't add attribute $flag. You need to know when you select only admins and when all users. Downside: you need to create separate relation for every flag value.


    Your solution with using separate model UserGroup still is more flexible and universal for all cases. Like you can add validation and basic ActiveRecord stuff. These solutions are more one way direction - to get stuff out.

提交回复
热议问题