Yii:CGridView - 来自父表的两行

时间:2015-03-15 23:42:33

标签: yii relation cgridview

Yii:1.1.15

直到现在我用CGridView做了很多 - 现在我遇到了一个简单的事情:在CGridView中我想显示来自父表的两个不同行的数据:

table / model:people(parent-table)

id    name
1     Bush
2     Heineken
3     Miller
4     Gonzales

table / model:friends(child-table)

id    friend1_id friend2_id
1     1          3
2     2          4

在模型Frinds.php中我有一个关系:

public function relations() {
    return array(
        'people' => array(self::BELONGS_TO, 'People', 'friend1_id')
}

在我的CGridview中,我希望看到 - 而且我不知道如何:

id  friend1   friend2
1   Bush      Miller
2   Heineken  Gonzales

1 个答案:

答案 0 :(得分:0)

所以我知道你有一个People表,你可以存储所有用户,还有一个Friends表,你可以为两个用户之间的每个友谊存储一行。

现在我猜你的网格正在为Friends模型获得结果吗?

你应该:

1)在Friends模型中正确定义两个关系:

public function relations() {
    return array(
        'friend1' => array(self::BELONGS_TO, 'People', 'friend1_id'),
        'friend2' => array(self::BELONGS_TO, 'People', 'friend2_id'),
    );
}

2)现在,在您的好友模型中添加两​​个新属性:

class Friends extends CActiveRecord {

  public $friend1Name;
  public $friend2Name;

...

3)现在,您可以在网格中使用此类列:

'columns' => array(
    'friend1Name'=>array(
        'name'=>'friend1Name',
        'value'=>'$data->friend1->name',
    ),
    'friend2Name'=>array(
        'name'=>'friend2Name',
        'value'=>'$data->friend2->name',
    ),

4)您添加的两个属性现在没有标签,您可以从attributeLabels自定义

public function attributeLabels() {
    return array(
      'friend1Name' => 'Friend 1 name',
      'friend2Name' => 'Friend 2 name',

5)此外,如果你调整好友模型搜索()方法,你可以再做两件事:

  • 由于你是懒人加载模型,Yii会向数据库发出一个sql请求,让每个朋友,如果你每页显示10个结果,这将是20个请求,把它变成只有一个你可以使用$ criteria-> with(),并将join1和friend2关系与joinType内连接放在一起。

  • 其次,您可以在单击网格列时对结果进行排序,因为您可以在search()方法返回的CActiveDataProvider中添加排序配置,并映射friend1Name和friend2Name以按相应的字段排序在关系中。

更新:其他要点:

public function search() {

    //... compare conditions here

    /* 6) Run only one SQL query by joining tables instead of one query per every Person */
    $criteria->with=array(
        'friend1'=>array(
            'joinType'=>'INNER JOIN',
        ),
        'friend2'=>array(
            'joinType'=>'INNER JOIN',
        ),
    );

    /* Tip: You can use with() and not use the joinType but by using it we are forcing a INNER JOIN that makes sense in this case */

    return new CActiveDataProvider($this, array(
        'criteria'=>$criteria,

        /* 7) Apply sorting for the columns from the related tables */
        'sort'=>array(
          'attributes'=>array(
              '*',
              'friend1Name'=>array(
                  'asc'=>'friend1.name',
                  'desc'=>'friend1.name desc',
              ),
              'friend2Name'=>array(
                  'asc'=>'friend2.name',
                  'desc'=>'friend2.name desc',
              ),
          ),
        ),
    ));

}

/* 8) Auto-fill friend1Name and friend2Name with the names from the related tables */
protected function afterFind () {

    $this->friend1Name=$this->friend1->name;
    $this->friend2Name=$this->friend2->name;

    // Tip: Now you can use in your grid directly friend1Name instead of $data->friend1->name

    parent::afterFind();
}