在CGridView里,可以用CSqlDataProvider代替CActiveDataProvider来进行更加复杂的查询。CActiveDataProvider使用的是面向对象的思想,如果你想join一张表,你得做两件事情:
-
给这张表生成一个模型,比如说叫它UserGroupAssignment
-
在model的relation里定义外键关联的属性,比如说Users,关系是MANY_MANY
-
定义一个CDbCriteria,用with来eager load这个属性Users
然后就可以查询了,但是问题在于tbl_UserGroupAssignment这张表可不单单是用来做多对多的关联用的,这张表有三个字段,分别是uid,gid,role。也就是说,还有一个很重要的字段是role,但是relation定义出来的属性Users属于user表,里面是没有role字段的,于是问题就来了。比如说我想查询群组gid = 1里所有role为member的用户,怎么办?role属性不存在于任何一个对象中!麻烦就大了!
这时候传统的sql语句就可以排上用场了,使用CSqlDataProvider可以灵活地处理这个问题,我只举一个简单的例子,并没有涉及上面的join,你可以自己发挥。
controller:
$count = Yii::app()->db->createCommand('SELECT COUNT(*) FROM tbl_user')->queryScalar(); $sql = 'SELECT * FROM tlb_user'; $dataProvider = new CSqlDataProvider($sql, array( 'totalItemCount' => $count, 'sort' => array( 'attributes' => array( 'name', ) ), 'pagination' => array( 'pageSize' => 10 ) )); $this->render('addExperts',array( 'dataProvider'=>$dataProvider, ));
view:
<?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'menu-grid', 'dataProvider'=>$dataProvider, 'columns'=>array( array( 'id'=>'autoId', 'class'=>'CCheckBoxColumn', 'selectableRows' => '50', ), 'name', ), )); ?>
效果:
SQLdataprovider不方便的地方在于,需要写一句一共多少条记录,查出来的记录是纯数组而不是AR类型数组,所以在显示的时候很麻烦,无法用到AR类中的辅助显示的成员函数。比如查出来一个字段是0或1,你不能直接显示给用户看,至少要变成是和否,这一下变换一般是在AR类中完成的,可是数组又用不了。这还是最简单的情况,一些复杂的显示可能要另开炉灶复制粘贴一大段代码,造成代码维护艰难和难以阅读。