定义通过其他模型到同一模型的关系


Yii Define relation to same model through other model

在我的Yii应用程序中,我有2个模型,配置文件和组。每个概要文件属于由概要文件定义的组。GroupID是Groups.GroupID的FK。此外,每个组都有一个管理器(Group. managerid),它基本上是另一个配置文件(因此,它引用了表Users中的user_id)。

在模型概要文件中,我想定义一个关系,这样,对于给定的概要文件,我可以很容易地检索管理器。

下面是代表两个模型的两个表中的一些示例数据:

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

如有任何建议,不胜感激。

您可以使用关系,您必须创建两个"BELONGS_TO""HAS_ONE"关系一个在Profiles模型中,另一个在Groups模型中:

,例如在Profiles:

public function relations() {
    'group' => ...
}

in Groups:

public function relations() {
    'manager' => ...
}

,然后你可以得到像$user->group->manager这样的具体用户的管理器。

但是在这种情况下,使用生成两个JOINs ,如果您的表很大,这可能会很慢。

或者您可以只使用一个关系(用于获取用户组)和一个查询来获取管理器:在Profiles模型中创建公共变量$manager并将其添加到模型规则中(例如在搜索中)

public $manager = null;

和重写方法afterFind:

public function afterFind() {
    $this->manager = self::model()->findByAttributes('user_id' => $this->group->manager_id);
    return parent::afterFind()
}

如果您使用第一个方法(两个关系),您可以覆盖您的DataProviderSort对象(例如在您的模型的"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列中添加/更改列

array(
    'name'=>'managerLastname',
    'value'=>'$data->group->manager->lastName'
) // be sure that each user has manager

并在模型中添加公共属性managerLastname

谢谢。

我认为是这样的(未经测试):

public function getManager() {
    $this->hasOne(Profiles::className(), ['user_id' => 'manager_id'])->viaTable('{{%groups}}', ['group_id' => 'group_id']);
}