PHP的Yii框架的基本使用示例 |
|
本文标签:PHP,Yii 在 Yii 自动生成的代码里,我们总能在 admin 的界面看到 CGridView 的身影 。这是一个很好用的展示数据的表格控件,用的好可以明显地加快开发进度 。下面就让我们来探索一下 CGridView 的基本使用吧: 简单起见,我们的代码就用 Yii demo 中的 blog 例子来做修改 。首先,这是修改后的部分 Mysql 语句:
drop table if exists `tbl_user`;
CREATE TABLE tbl_user
(
`user_id` INTEGER NOT NULL AUTO_INCREMENT comment 主键,
`username` VARCHAR(128) NOT NULL comment 用户名,
`nickname` VARCHAR(128) NOT NULL comment 昵称,
`password` VARCHAR(128) NOT NULL comment 密码,
`email` VARCHAR(128) NOT NULL comment 邮箱,
`is_delete` tinyint not null default 0 comment 删除标志,
unique key(`username`),
primary key (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 comment=用户表;
drop table if exists `tbl_post`;
CREATE TABLE tbl_post
(
`post_id` INTEGER NOT NULL AUTO_INCREMENT comment 主键,
`title` VARCHAR(128) NOT NULL comment 标题,
`content` TEXT NOT NULL comment 文章内容,
`tags` TEXT comment 标签,
`status` INTEGER NOT NULL comment 状态,0 = 草稿,1 = 审核通过,-1 = 审核不通过,2 = 发布,
`create_time` INTEGER comment 创建时间,
`update_time` INTEGER comment 更新时间,
`author_id` INTEGER NOT NULL comment 作者,
`is_delete` tinyint not null default 0 comment 删除标志,
CONSTRAINT `post_ibfk_1` FOREIGN KEY (author_id)
REFERENCES tbl_user (`user_id`) ON DELETE CASCADE ON UPDATE RESTRICT,
primary key (`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 comment=日志表;
两个表一个存储作者信息一个存储日志,其中日志有一个外键关联到 user 。两个表里面的 is_delete 字段是标志该条记录是否被删除,0 为未删除,1 为已删除 。让我们看一下用 gii 生成的 Post 类的 relation 方法:
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
comments => array(self::HAS_MANY, Comment, post_id),
author => array(self::BELONGS_TO, User, author_id),
);
}
其中的 author 外键作为 BELONGS_TO 关系存在,符合我们的预期 。
<?php $this->widget(zii.widgets.grid.CGridView, array(
id=>post-grid,
dataProvider=>$model->search(),
filter=>$model,
columns=>array(
post_id,
title,
content,
tags,
status,
create_time,
update_time,
author_id,
is_delete,
array(
class=>CButtonColumn,
),
),
)); ?>
看!虽然我们什么都没写,但这就是这个控件的最基础使用了 。dataProvider 是由 model 里面的 search 函数提供的数据,filter...暂时看不出这里的作用,columns 控制展示的每一列,其中最后一项的 CButtonColumn 向我们展示了三个按钮,分别是 查看 更新 和 删除 。 用 CGridView 展示我们真正要的数据形式:
<?php $this->widget(zii.widgets.grid.CGridView, array(
id=>post-grid,
dataProvider=>$model->search(),
filter=>$model,
columns=>array(
post_id,
title,
content,
tags,
status,
create_time,
update_time,
author_id,
is_delete,
array(
name=>is_delete,
value=>is_delete?"是":"否" //value 是可以执行 php 语句的哦
)
array(
class=>CButtonColumn,
),
),
)); ?>
除此之外,还有一些常用的选项,都可以在 array 里面填写,下面是比较常见的使用方式(其他部分代码省略): array( name=>is_delete, value=>is_delete?"是":"否" //value 是可以执行 php 语句的哦 filter => array(0=>否,1=>是), //自己定义搜索过滤的方式,这里为 是 和 否 的下拉菜单 htmlOptions=>array(class=>delete), //可以定义 html 选项,这里是定义了带一个 delete 的类 ), 上面我们用 name 的话那是 model 里原来就有的字段,如果我们想展示自己定义的新内容呢,用 header : array( header=>备注, value=> display your data ), 添加 CCheckBoxColumn :
<?php $this->widget(zii.widgets.grid.CGridView, array(
id=>post-grid,
dataProvider=>$model->search(),
filter=>$model,
columns=>array(
array(
selectableRows => 2, //允许多选,改为 0 时代表不允许修改,1 的话为单选
class => CCheckBoxColumn,//复选框
headerHtmlOptions => array(width=>18px),//头部的 html 选项
checkBoxHtmlOptions => array(name => myname,class=>myclass), //复选框的 html 选项
),
post_id,
title,
content,
tags,
status,
create_time,
update_time,
author_id,
is_delete,
array(
name=>is_delete,
value=>is_delete?"是":"否", //value 是可以执行 php 语句的哦
filter => array(0=>否,1=>是), //自己定义搜索过滤的方式,这里为 是 和 否 的下拉菜单
htmlOptions=>array(class=>delete), //可以定义 html 选项,这里是定义了带一个 delete 的类
),
array(
class=>CButtonColumn,
),
),
));
修改ButtonColumn:
array(
class=>ButtonColumn,
template=>"{view} {update}",
),
也可以自定义按钮:
array(
class=>ButtonColumn,
template=>"{view} {update} {print}",
buttons=>array(
print=>array(
label=>打印,
url=>Yii::app()->controller->createUrl("print", array("id"=>$data->post_id)),
options=>array("target"=>"_blank"),
),
),
),
刷新时触发 Javascript:
$js = <<<_JS_
function(){
alert(The ajax finish);
}
_JS_;
$this->widget(zii.widgets.grid.CGridView, array(
id=>post-grid,
dataProvider=>$model->search(),
filter=>$model,
afterAjaxUpdate=>$js, //看这里,ajax 之后调用的 javascript 在这里....
columns=>array(
array(
selectableRows => 2, //允许多选,改为 0 时代表不允许修改,1 的话为单选
class => CCheckBoxColumn,//复选框
headerHtmlOptions => array(width=>18px),
checkBoxHtmlOptions => array(name => myname,class=>myclass),
),
....
添加 关联表 相关字段的搜索:
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
comments => array(self::HAS_MANY, Comment, post_id),
author => array(self::BELONGS_TO, User, author_id),
);
}
可以看到 POST 和 USER 表可以通过 author 键进行访问,例如: $model->author->nickname,而且 这里是 BELONGS_TO 关系 。 产品经理推了推眼镜:”我们要在日志的后台管理界面加一个功能,可以通过作者名称搜索到相应的文章 。这个比较急,今晚就要完成 。“ 淡定淡定,不就是改需求吗 。忽略进度要求,我们研究一下究竟要做什么 。 首先,我们进入 POST 的 model,在一开始的地方添加一个属性:
class Post extends CActiveRecord
{
public $name; //添加一个 public 属性,代表作者名
然后改一下 Model 里面 search 的代码,改动部分都已经加了注释:
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->with = array(author); //添加了和 author 的渴求式加载
$criteria->compare(post_id,$this->post_id);
$criteria->compare(title,$this->title,true);
$criteria->compare(content,$this->content,true);
$criteria->compare(tags,$this->tags,true);
$criteria->compare(status,$this->status);
$criteria->compare(create_time,$this->create_time);
$criteria->compare(update_time,$this->update_time);
$criteria->compare(author_id,$this->author_id);
//这里添加了一个 compare, username 是 User 表的字段,$this->name 是我们添加的属性,true 为模糊搜索
$criteria->compare(username,$this->name,true);
return new CActiveDataProvider($this, array(
criteria=>$criteria,
));
}
<?php $this->widget(zii.widgets.grid.CGridView, array(
id=>post-grid,
dataProvider=>$model->search(),
filter=>$model,
columns=>array(
post_id,
title,
content,
tags,
status,
create_time,
update_time,
author_id,
/*下面就是添加的代码啊*/
array(
name=>作者名称,
value=>$data->author->username, //定义展示的 value 值
filter=>CHtml::activeTextField($model,name), //添加搜索 filter
),
array(
class=>CButtonColumn,
),
),
)); ?>
你是不是发现现在有了搜索框但是不起作用呢?哈哈,所以我们说文章要坚持看到最后 。我们要做的最后一步,就是在 rule 里面,把 name 属性加入到安全搜索字段中,要不然会被 Yii 认为是不安全字段而过滤掉的 。看,就在下面函数的最后一行,safe 前面多了个 name ....
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array(title, content, status, author_id, required),
array(status, create_time, update_time, author_id, numerical, integerOnly=>true),
array(title, length, max=>128),
array(tags, safe),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array(post_id, title, content, tags, status, create_time, update_time, author_id, name, safe, on=>search),
);
}
|