Retrieve data from junction table in Yii2

前端 未结 4 1204
离开以前
离开以前 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:57

    In short: Using an ActiveRecord for the junction table like you suggested is IMHO the right way because you can set up via() to use that existing ActiveRecord. This allows you to use Yii's link() method to create items in the junction table while adding data (like your admin flag) at the same time.


    The official Yii Guide 2.0 states two ways of using a junction table: using viaTable() and using via() (see here). While the former expects the name of the junction table as parameter the latter expects a relation name as parameter.

    If you need access to the data inside the junction table I would use an ActiveRecord for the junction table as you suggested and use via():

    class User extends ActiveRecord
    {
        public function getUserGroups() {
            // one-to-many
            return $this->hasMany(UserGroup::className(), ['user_id' => 'id']);
        }
    }
    
    class Group extends ActiveRecord
    {
        public function getUserGroups() {
            // one-to-many
            return $this->hasMany(UserGroup::className(), ['group_id' => 'id']);
        }
    
        public function getUsers()
        {
            // many-to-many: uses userGroups relation above which uses an ActiveRecord class
            return $this->hasMany(User::className(), ['id' => 'user_id'])
                ->via('userGroups');
        }
    }
    
    class UserGroup extends ActiveRecord
    {
        public function getUser() {
            // one-to-one
            return $this->hasOne(User::className(), ['id' => 'user_id']);
        }
    
        public function getGroup() {
            // one-to-one
            return $this->hasOne(Group::className(), ['id' => 'userh_id']);
        }
    }
    

    This way you can get the data of the junction table without additional queries using the userGroups relation (like with any other one-to-many relation):

    $group = Group::find()->where(['id' => $id])->with('userGroups.user')->one();
    // --> 3 queries: find group, find user_group, find user
    // $group->userGroups contains data of the junction table, for example:
    $isAdmin = $group->userGroups[0]->adminFlag
    // and the user is also fetched:
    $userName = $group->userGroups[0]->user->name
    

    This all can be done using the hasMany relation. So you may ask why you should declare the many-to-many relation using via(): Because you can use Yii's link() method to create items in the junction table:

    $userGroup = new UserGroup();
    // load data from form into $userGroup and validate
    if ($userGroup->load(Yii::$app->request->post()) && $userGroup->validate()) {
        // all data in $userGroup is valid
        // --> create item in junction table incl. additional data
        $group->link('users', $user, $userGroup->getDirtyAttributes())
    }
    

提交回复
热议问题