使用Yii的CGridView作为表格控件来展示数据,方法很简单,在模型中定义search函数,视图中使用如下:
<?php $this->widget('application.extensions.grid.FGridView', array( 'id'=>'grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( 'id', 'status', 'created', 'Detail.subject', 'Category.title' ) ));?>
现在的问题是需要显示多个关联表格的数据,比如这样3个表:Deal, Category, Detail
关系是Deal has many Details, Deal belongs to Category
要把分类标识(Category::title)和产品标题(Detail::subject)显示在同一张表格中。
那么直接的想法就是把上面视图代码修改为:
<?php $this->widget('application.extensions.grid.FGridView', array(
'id'=>'grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'status',
'created',
'Category.title', 'Detail.subject'
)
));?>
不过这样只能显示数据,不能对这两个新增字段进行过滤和排序。
解决方法需要针对上面两种不同的情况做出处理:
1、对BELONGS_TO关系的处理即Category.title,这个已经有文章详细描述,可参见
http://www.mrsoundless.com/post/2011/05/09/Searching-and-sorting-a-column-from-a-related-table-in-a-CGridView.aspx
思路就是
*)为模型添加属性及其读写方法
*)然后定义关联关系(relations)
*)添加新字段到搜索规则中
*)使用with进行积极关联查询,设置相应的criteria和sort,其中新属性前缀使用关联表名,如:
public function relations() { return array( 'DealDetails' => array(self::HAS_MANY, 'DealDetail', 'deal_id'), ); }
......//in search function $criteria->compare('Category.title','KTV'); ......
2、对HAS_MANY/MANY_MANY关系的处理要复杂些,这里以HAS_MANY为例。
Detail在关联查询结果中是数组形式的数据,直接通过Detail.subject是访问不到正确的产品标题数据的。
需要对数组数据进行过滤,得到唯一的值,因此需要实现一个获取唯一产品标题的方法,比如:
public function getSubject() { if ($this->_subject === null && $this->DealDetails !== null){ foreach($this->DealDetails as $dealdetail) { if($dealdetail->lang_id == '2')//english $this->_subject = $dealdetail->subject; } } return $this->_subject; }
然后在搜索条件中使用该方法。
上面说的是搜索,下面简单说明排序的实现,思路是传递sort实例给数据容器对象。
上面说的是搜索,下面简单说明排序的实现,思路是传递sort实例给数据容器对象。
......//in search function $sort = new CSort(); $sort->attributes = array( 'defaultOrder'=>'t.created DESC', 'status'=>array( 'asc'=>'t.status', 'desc'=>'t.status desc', ), 'subject'=>array( 'asc'=>'DealDetails.subject', 'desc'=>'DealDetails.subject desc', ), 'created' ); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, 'pagination'=>array( 'pageSize'=>10, ), 'sort'=>$sort )); ......