Yii 通过其他模型定义与同一模型的关系
Yii Define relation to same model through other model
在我的 Yii 应用程序中,我有 2 个模型,配置文件和组。
每个配置文件都属于 Profiles.GroupID 定义的组,该组是 Groups.GroupID 的 FK。
此外,每个组都有一个经理 (Group.ManagerID),这基本上是另一个配置文件(因此,它在 table 用户中引用 user_id)。
在模型配置文件中,我想定义一个关系,以便对于给定的配置文件,我可以轻松地检索管理器。
下面是来自两个 table 的一些示例数据,代表 2 个模型配置文件、组:
Table Profiles
user_id firstname lastname group_id
------- ----------- ---------- -------
1 John Doe 100
2 Walter White 200
3 Gus Fring 100
4 Biggie Smalls 200
Table: Groups
group_id manager_id
------- ---------
100 2
200 4
如有任何建议,我们将不胜感激。
我觉得是这样的(未测试):
public function getManager() {
$this->hasOne(Profiles::className(), ['user_id' => 'manager_id'])->viaTable('{{%groups}}', ['group_id' => 'group_id']);
}
将这个函数放在 Profiles 模型中。
您可以使用关系,您必须创建两个 "BELONGS_TO"
和 "HAS_ONE"
关系,一个在 Profiles
模型中,第二个在 Groups
模型中:
例如 Profiles
:
public function relations() {
'group' => ...
}
在Groups
中:
public function relations() {
'manager' => ...
}
然后你可以获得像这样的具体用户的经理$user->group->manager
。
但在这种情况下生成查询 两个 JOINs
,如果您的表很大,这可能会很慢。
或者你可以只使用一个关系(用于获取用户组)和一个用于获取经理的查询:
在 Profiles
模型中创建 public 变量 $manager
并将其添加到您的模型规则中(f.e 在搜索中)
public $manager = null;
并覆盖方法 afterFind
:
public function afterFind() {
$this->manager = self::model()->findByAttributes('user_id' => $this->group->manager_id);
return parent::afterFind()
}
已编辑
如果您使用第一种方法(两个关系),您可以覆盖 DataProvider
的 Sort
对象(f.e。在模型的方法 "sort"
中) :
public function search() {
$criteria = new CDbCriteria;
$sort = new CSort;
$sort->defaultOrder = 'someField ASC';
$sort->attributes = array(
'*',
'managerLastname' => array(
'ASC' => 'group.manager.lastname ASC',
'DESC' => 'group.manager.lastname DESC',
)
);
// .....other criterias
$criteria->compare('managerLastname', $this->group->manager->lastname, true); // for filtering
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'sort' => $sort
));
}
并在 CGgridView
列中 add/change 列
array(
'name'=>'managerLastname',
'value'=>'$data->group->manager->lastName'
) // be sure that each user has manager
并在您的模型中添加 public 属性 managerLastname
。
谢谢。
在我的 Yii 应用程序中,我有 2 个模型,配置文件和组。 每个配置文件都属于 Profiles.GroupID 定义的组,该组是 Groups.GroupID 的 FK。 此外,每个组都有一个经理 (Group.ManagerID),这基本上是另一个配置文件(因此,它在 table 用户中引用 user_id)。
在模型配置文件中,我想定义一个关系,以便对于给定的配置文件,我可以轻松地检索管理器。
下面是来自两个 table 的一些示例数据,代表 2 个模型配置文件、组:
Table Profiles
user_id firstname lastname group_id
------- ----------- ---------- -------
1 John Doe 100
2 Walter White 200
3 Gus Fring 100
4 Biggie Smalls 200
Table: Groups
group_id manager_id
------- ---------
100 2
200 4
如有任何建议,我们将不胜感激。
我觉得是这样的(未测试):
public function getManager() {
$this->hasOne(Profiles::className(), ['user_id' => 'manager_id'])->viaTable('{{%groups}}', ['group_id' => 'group_id']);
}
将这个函数放在 Profiles 模型中。
您可以使用关系,您必须创建两个 "BELONGS_TO"
和 "HAS_ONE"
关系,一个在 Profiles
模型中,第二个在 Groups
模型中:
例如 Profiles
:
public function relations() {
'group' => ...
}
在Groups
中:
public function relations() {
'manager' => ...
}
然后你可以获得像这样的具体用户的经理$user->group->manager
。
但在这种情况下生成查询 两个 JOINs
,如果您的表很大,这可能会很慢。
或者你可以只使用一个关系(用于获取用户组)和一个用于获取经理的查询:
在 Profiles
模型中创建 public 变量 $manager
并将其添加到您的模型规则中(f.e 在搜索中)
public $manager = null;
并覆盖方法 afterFind
:
public function afterFind() {
$this->manager = self::model()->findByAttributes('user_id' => $this->group->manager_id);
return parent::afterFind()
}
已编辑
如果您使用第一种方法(两个关系),您可以覆盖 DataProvider
的 Sort
对象(f.e。在模型的方法 "sort"
中) :
public function search() {
$criteria = new CDbCriteria;
$sort = new CSort;
$sort->defaultOrder = 'someField ASC';
$sort->attributes = array(
'*',
'managerLastname' => array(
'ASC' => 'group.manager.lastname ASC',
'DESC' => 'group.manager.lastname DESC',
)
);
// .....other criterias
$criteria->compare('managerLastname', $this->group->manager->lastname, true); // for filtering
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'sort' => $sort
));
}
并在 CGgridView
列中 add/change 列
array(
'name'=>'managerLastname',
'value'=>'$data->group->manager->lastName'
) // be sure that each user has manager
并在您的模型中添加 public 属性 managerLastname
。
谢谢。