Yii中CGridView单元格组件和数据提供者的使用

CGridView组件是Zii库组件,主要用来展示表格式的数据,默认Gii生成的admin视图就用它展示

参考Yii手册可以发现,CGridView类位于Zii.widgets.grid命名空间下,所以它就是个单元格部件,Zii.widgets.grid命名空间下只有CGridView类和配合它工作的一些CXxxColumn类(表示不同的列对象)。

CGridView属于视图部件,所以,基本用法和不含body内容的部件相同,即  $this->widget('类名',   array(key-value参数对));

最简短的代码如下:

$dataProvider=new CActiveDataProvider('Post');

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$dataProvider,
));


即参数只有1个:数据提供者,常见数据提供者有3种:CActiveDataProvider(对应AR模型)、CArrayDataProvider(对应二维数组)、CSqlDataProvider(对应SQL查询返回的数据),cookbook的第7章提供了例子说明CGridView如何使用这3种数据提供者。Yii手册说明推荐使用CActiveDataProvider,即AR模型数据作为数据提供者。

CActiveDataProvider、CArrayDataProvider、CSqlDataProvider及它们的基类CDataProvider、接口IDataProvider都在system.web下,这三个数据提供者中数组类型最直观,常见的属性是通用的排序sort和分页pagination。SQL类型的提供者默认使用了Yii::app()->db这个连接,所以构造数据提供者时可以不指定db连接而直接给出SQL语句,但必须同时给出SQL语句返回的记录个数(不然无法实现分页),所以,往往包含了2个SQL语句。SQL类型的数据提供者,可以用$dataProvider->getData()获取数组形式的数据。

CActiveDataProvider是最复杂的提供者,它基于AR,并使用了AR的CActiveRecord::findAll()方法来获取数据,也正因为如此,构造这类数据提供者时,需要指明对应的Model,提供查询标准criteria参数。和SQL类型提供者一样,也可以用$dataProvider->getData()获取数组形式的数据。

CActiveDataProvider构造的例子(获取不在某个组的用户作为提供者):

        public function searchNotInGroup(Group $group)
        {
            $connection = Yii::app()->db;
            $sql = 'select user_id from {{role}} except select user_id from {{role}} where '.
                'group_id='.$group->id;
            $command = $connection->createCommand($sql);
            $rows = $command->queryAll();
            $user_ids = array();
            foreach($rows as $row)  $user_ids[] = $row['user_id'];
            
            return new CActiveDataProvider('User', array(
                'criteria' => array(
                    'condition' => 'id in ('.implode(',', $user_ids).')',
                    'order' => 'username',
                ),
                'pagination' => array(
                    'pageSize' => 3,
                ),
            ));
        }



CGridView 的一个重要属性是filter:一个模型实例参数,它保存了用户输入的过滤器数据(即单元格组件标题行下的那些输入框)

CGridView的另一个重要属性是columns:一个array,用来配置单元格,即应该显示哪些列,怎么显示。这个array类型中的每个元素对应一个列,每个元素的类型可以是string或array。当元素是string类型时,其格式必须是"name:type:header",因为最终会产生CDataColumn类型的实例,这三部分和CDataColumn的3个属性对应。当元素是array类型时,最终创建某种grid column实例(基类型CGridColumn),用'class'元素指明子类型(当前zii库提供CDataColumn[缺省时为此类型]、CLinkColumn、CButtonColumn、CCheckBoxColumn)。admin视图中前面几列都是CDataColumn类型,最后的那些按钮列是CButtonColumn类型。下面给出CLinkColumn类型的例子:

//GroupController
        public function actionView($id)
        {
            $usermodel = new User('searchNotInGroup');
            $usermodel->unsetAttributes(); // clear any default values
            if (isset($_GET['User']))
                $usermodel->attributes = $_GET['User'];

            $this->render('view', array('model' => $this->loadModel($id), 'usermodel' => $usermodel));
        }

//group/view/$id
    $this->widget('zii.widgets.grid.CGridView', array(
	'id'=>'user-grid',
	'dataProvider'=>$usermodel->searchNotInGroup($model),
	'filter'=>$usermodel,
	'columns'=>array(
        'id',
		'username',
        array(
            'name' => 'status',
            'value' => 'Lookup::item("userStatus", $data->status)',
            'filter' => Lookup::items('userStatus'),
        ),
		array(
			'class'=>'CLinkColumn',
            'labelExpression' => '"添加用户".$data->username', 
            'urlExpression' => 'array("group/addUser", "id" =>'. $model->id .', "userid" => $data->id)'
		),
	),
));  


说明:上述加载的CGridView中,状态列是CDataColumn类型:用'name'对应数据模型的属性名,'filter'对应过滤器输入(文本或dropdownlist的数据,这里是后者)。'value'对应的是字符串,但这些字符串代表一个PHP表达式,这个表达式会针对每行数据进行计算,计算的结果就是最后在单元格显示的内容。PHP表达式中,变量$row代表行号(从0开始),$this代表列对象,$data代表该行的数据模型,所以,上面的例子中,$data->status代表该行对应的User数据模型实例的状态。

上述例子中,最后一列是CLinkColumn类型,所以,用'class'指明类,'label'是显示的文字,'url'是对应的链接,如果显示的文字和对应的链接是含参数的,可以分别换成'labelExpression'和'urlExpression‘来指定,其中可以使用$row、$this、$data等变量(和上面的'value'内的情况一样)。阅读CLinkColumn类的源码,只有唯一的protected方法renderDataCellContent($row, $data)

 protected function renderDataCellContent($row,$data)
        {
                if($this->urlExpression!==null)
                        $url=$this->evaluateExpression($this->urlExpression,array('data'=>$data,'row'=>$row));
                else
                        $url=$this->url;
                if($this->labelExpression!==null)
                        $label=$this->evaluateExpression($this->labelExpression,array('data'=>$data,'row'=>$row));
                else
                        $label=$this->label;
                $options=$this->linkHtmlOptions;
                if(is_string($this->imageUrl))
                        echo CHtml::link(CHtml::image($this->imageUrl,$label),$url,$options);
                else
                        echo CHtml::link($label,$url,$options);
        }


可以知道,使用了urlExpression和labelExpression,是通过evaluateExpression计算得到url和label的。evaluateExpression是CLinkColumn的基类方法,它的第一个参数是一个PHP表达式或PHP回调,第二个参数是传递给表达式或回调的附加参数。

        public function evaluateExpression($_expression_,$_data_=array())
        {
                if(is_string($_expression_))
                {
                        extract($_data_);
                        return eval('return '.$_expression_.';');
                }
                else
                {
                        $_data_[]=$this;
                        return call_user_func_array($_expression_, $_data_);
                }
        }

在我们的例子中,urlExpression是一个PHP表达式(字符串),即'urlExpression' => 'array("group/addUser", "id" =>'. $model->id .', "userid" => $data->id)',这一句相当于翻译成了$urlExpression =  array("group/addUser", "id" =>'. $model->id .', "userid" => $data->id);   然后Yii会以它的生成URL的方式利用这个数组,生成类似r=group/addUser&id=2&userid=1 的链接。

evaluateExpression第二个参数是数组形式的,执行时会用PHP函数extract解析该数组并插入变量,即键作为变量名,值作为变量值,$url = $this->evaluateExpression($this->urlExpression, array('data' => $data, 'row'=>$row)); 翻译成

$data = $data值;

$row = $row值;

$url = $this->urlExpression中代入$data,$row值得到的结果;


根据手册说明,evaluateExpression第一个参数也可以是PHP回调:即一个类的方法,格式为array(类名或实例, 方法名),也可以是匿名函数,并且方法签名或匿名函数的格式如下function foo($param1, $param2, ..., $component) { ... },从上面evaluateExpression的源码中也可以知道,最后一个参数是组件自身,而之前的参数就是我们以数组形式传递的变量和对应值。


CGridView、数据提供者、使用表达式或回调作为参数这些东西所采用的思维,在整个Yii框架中随处可见,所以值得深究


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值