msf*_*fgt 11 php mysql activerecord yii2
我正在尝试从Yii2中的连接表中获取数据,而无需额外的查询.我有2个模型(用户,组)通过联结表(user_group)关联.在user_group表中,我想为此关系存储额外数据(admin flag,...).
将数据添加到联结表的最佳方法是什么?link方法接受参数extraColumns但我无法弄清楚它是如何工作的.
检索此数据的最佳方法是什么?我写了一个额外的查询来从连接表中获取值.必须有一个更清洁的方法来做到这一点?!
仅供参考,这是我在模型中定义关系的方式:
Group.php
public function getUsers() {
return $this->hasMany(User::className(), ['id' => 'user_id'])
->viaTable('user_group', ['group_id' => 'id']);
}
Run Code Online (Sandbox Code Playgroud)
user.php的
public function getGroups() {
return $this->hasMany(Group::className(), ['id' => 'group_id'])
->viaTable('user_group', ['user_id' => 'id']);
}
Run Code Online (Sandbox Code Playgroud)
简而言之:ActiveRecord
像你建议的那样使用连接表是恕我直言,因为你可以设置via()
使用现有的ActiveRecord
.这允许您使用Yii的link()
方法在联结表中创建项目,同时添加数据(如管理标志).
官方的Yii Guide 2.0说明了两种使用联结表的方法:使用viaTable()
和使用via()
(见这里).虽然前者期望联结表的名称作为参数,但后者期望关系名称作为参数.
如果您需要访问联结表中的数据,我会ActiveRecord
按照您的建议使用连接表并使用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']);
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以使用userGroups
关系获取联结表的数据而无需其他查询(与任何其他一对多关系一样):
$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
Run Code Online (Sandbox Code Playgroud)
这一切都可以使用hasMany
关系来完成.因此,您可能会问为什么要使用以下方法声明多对多关系via()
:因为您可以使用Yii的link()
方法在联结表中创建项目:
$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())
}
Run Code Online (Sandbox Code Playgroud)
由于我已经近 14 天没有收到任何答复,我将发布我如何解决这个问题。这并不完全是我想要的,但它有效,现在就足够了。所以...这就是我所做的:
添加了与组的关系
public function getUserGroups()
{
return $this->hasMany(UserGroup::className(), ['user_id' => 'id']);
}
Run Code Online (Sandbox Code Playgroud)在我的搜索模型功能中加入 UserGroup
$query = Group::find()->where('id =' . $id)->with('users')->with('userGroups');
Run Code Online (Sandbox Code Playgroud)这就是我想要的,包含所有用户的组,以及由我的新模型UserGroup表示的来自联结表的数据。
我考虑首先扩展查询构建 Yii2 函数 - 这可能是解决这个问题的更好方法。但由于我还不太了解 Yii2,所以我决定暂时不做。
如果您有更好的解决方案,请告诉我。