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
I don't know for sure it is best solution. But for my project it will be good for now :)
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.
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.
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.