目标
接着上一篇末尾,修改views
和models
,添加搜索表单,定制GridView
。
安装kartik-v/yii2-widgets
这是一个我觉得比较好用,文档比较全的包,包含众多强大的表单控件,例如select2。
github主页:https://github.com/kartik-v/yii2-widgets
Packagist主页:https://packagist.org/packages/kartik-v/yii2-widgets
英文文档(非常详尽):http://demos.krajee.com/widgets
随便放两个图感受一下select2:
支持图标分组
支持多选和全选(google翻译的)
如果执行时间超过10分钟,参考composer的注意事项的方案。
composer require kartik-v/yii2-widgets "*"
composer require kartik-v/yii2-field-range "dev-master"
完整回显为:
C:\phpstudy\www\yii2-advance>composer require --prefer-dist kartik-v/yii2-widgets "*"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 23 installs, 0 updates, 0 removals
- Installing kartik-v/yii2-krajee-base (v1.8.8): Downloading (100%)
- Installing kartik-v/yii2-widget-typeahead (v1.0.1): Downloading (100%)
- Installing kartik-v/yii2-widget-touchspin (v1.2.1): Downloading (100%)
- Installing kartik-v/yii2-widget-timepicker (v1.0.3): Downloading (100%)
- Installing kartik-v/yii2-widget-switchinput (v1.3.1): Downloading (100%)
- Installing kartik-v/yii2-widget-spinner (v1.0.0): Downloading (100%)
- Installing kartik-v/yii2-widget-sidenav (v1.0.0): Downloading (100%)
- Installing kartik-v/yii2-widget-select2 (v2.0.9): Downloading (100%)
- Installing kartik-v/bootstrap-star-rating (v4.0.1): Downloading (100%)
- Installing kartik-v/yii2-widget-rating (v1.0.2): Downloading (100%)
- Installing kartik-v/yii2-widget-rangeinput (v1.0.1): Downloading (100%)
- Installing kartik-v/yii2-widget-growl (v1.1.1): Downloading (100%)
- Installing kartik-v/bootstrap-fileinput (v4.4.2): Downloading (100%)
- Installing kartik-v/yii2-widget-fileinput (v1.0.6): Downloading (100%)
- Installing kartik-v/dependent-dropdown (v1.4.5): Downloading (100%)
- Installing kartik-v/yii2-widget-depdrop (v1.0.4): Downloading (100%)
- Installing kartik-v/yii2-widget-datetimepicker (v1.4.4): Downloading (100%)
- Installing kartik-v/yii2-widget-datepicker (v1.4.2): Downloading (100%)
- Installing kartik-v/yii2-widget-colorinput (v1.0.3): Downloading (100%)
- Installing kartik-v/yii2-widget-alert (v1.1.0): Downloading (100%)
- Installing kartik-v/yii2-widget-affix (v1.0.0): Downloading (100%)
- Installing kartik-v/yii2-widget-activeform (v1.4.8): Downloading (100%)
- Installing kartik-v/yii2-widgets (v3.4.0): Downloading (100%)
Writing lock file
Generating autoload files
C:\phpstudy\www\yii2-advance>composer require kartik-v/yii2-field-range "dev-master"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing kartik-v/yii2-field-range (dev-master 5f7f349): Cloning 5f7f34977e from cache
Writing lock file
Generating autoload files
2017-7-24:
这地方执行的
composer require kartik-v/yii2-field-range "dev-master"
可能会出现执行失败,如果执行失败,尝试执行
composer require --prefer-dist kartik-v/yii2-field-range "*"
当前样式以及目标
当前视图效果:
状态那一栏的标题应该是年龄,之前打字打错了
当前\frontend\views\student\index.php
代码,其他文件的代码没有太大修改。
<?php
use yii\grid\GridView;
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $searchModel frontend\models\StudentSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Students';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="student-index">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a('Create Student', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'stuid',
'name',
'sex',
'age',
'chinese',
'math',
'english',
[
'attribute'=>'入学日期2',
'value'=>function($model){
return date('Y-m-d H:i:s',$model->in_time);
}
],
'born_time',
// 'other:ntext',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
修改目标:
- 修改表格宽度
- 删除最左边的自增编号
- 删除自带搜索表单创建自定义表单
- 操作栏添加自定义功能按钮,按钮功能为弹出模态框
表格样式及数据 GridView
参考:
yii2 GridView常见操作
gridview类结构(英文,不好啃)
定制数据显示
下面的代码没有说明路径的都在\frontend\views\student\index.php
删除默认搜索表单,左侧自增序列
搜索下面两行代码并注释
'filterModel' => $searchModel,//搜索表单
['class' => 'yii\grid\SerialColumn'],//自增序列
以性别这一列为例,搜索'sex',
替换为下面的代码。
[
//设置列标题
'attribute' => '性别',
//使用匿名函数构造数据
'value' => function($model){
//将(1,0)使用三目运算返回(男,女)
return $model->sex=='0'?'女':'男';
},
//设置table th的属性
'headerOptions' => ['style'=>"width:80px;text-align: center;"],
//设置table td的属性
'contentOptions'=>['style'=>"text-align: center;"]
],
可以看到定制之后的效果
其他实现方案:
定义表格宽度也可以使用下面的代码来注册css。
$this->registerCss(
<<<CSS
.table{
width:auto;
}
.table th,.table td{
width: 80px;
text-align: center;
}
CSS
);
将代码转化成文字也可以在models修改查询语句。
添加弹出层展示数据
在最后一列添加一个自定义按钮,使用ajax请求数据并展示。
添加按钮:
查找['class' => 'yii\grid\ActionColumn'],
并替换为以下代码。
[
//附加操作栏
'class' => 'yii\grid\ActionColumn',
"header" => "明细",
"template" => "{show_detail}",
"buttons" => [
"show_detail" => function ($url, $model, $key) {
return Html::a(
"<span class='glyphicon glyphicon-fire'></span>",
"javascript:;",
[
'class' => "show_detail",
'data-toggle'=>"modal",
'data-target'=>"#MyModal"//自己定义的弹出层
]);
},
],
],
这段代码定义了一个a链接,a链接中定义了一个span标签,span标签附带了一个火焰样式的图标。
图标资源:
Bootstrap Glyphicon Icons
Bootstrap中文网-组件
如果不需要图标,把<span class='glyphicon glyphicon-fire'></span>
改成你想显示的文字即可。
添加弹出层:
参考:
http://www.manks.top/yii2_modal_baseuse.html
在页面末尾添加下面代码,用于添加一个弹出层。
<?php
use yii\bootstrap\Modal;
Modal::begin([
'id' => 'MyModal',
'header' => '<h4 class="modal-title">明细</h4>',
'footer' => '<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>',
]);
Modal::end();
?>
在文件开头php区域添加下面的代码注册js,$this->registerJs()
的第二个参数为js放置的位置,第二个参数默认为View::POS_READY
,详情请参考最下面的附录。
use yii\helpers\Url;
$show_detailUrl = Url::toRoute('show_detail');
$updateJs = <<<JS
$('.show_detail').on('click', function () {
$.get('{$show_detailUrl}', { id: $(this).closest('tr').data('key') },
function (data) {
$('#MyModal .modal-body').eq(0).html(data);
}
);
});
JS;
$this->registerJs($updateJs);
打开\frontend\controllers\StudentController.php
添加一个方法。
public function actionShow_detail($id){
$model = $this->findModel($id);
return $this->renderPartial('show_detail', [
'model' => $model,
]);
}
创建\frontend\views\student\show_detail.php
,写入下面html
<div class="row clearfix">
<div class="col-md-12 column">
<div class="panel panel-default">
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item">学号:<?=$model->stuid?></li>
<li class="list-group-item">姓名:<?=$model->name?></li>
<li class="list-group-item">性别:<?=$model->sex?'男':'女'?></li>
<li class="list-group-item">年龄:<?=$model->age?></li>
<li class="list-group-item">语文:<?=$model->chinese?></li>
<li class="list-group-item">数学:<?=$model->math?></li>
<li class="list-group-item">外语:<?=$model->english?></li>
<li class="list-group-item">入学日期:<?=date('Y-m-d H:i:s',$model->in_time)?></li>
<li class="list-group-item">出生日期:<?=$model->born_time?></li>
<li class="list-group-item">备注:<?=$model->other?></li>
</ul>
</div>
</div>
</div>
</div>
bootstrap的样式拖拽生成:
菜鸟工具layoutit生成
bootstrap文档:
Bootstrap中文网(官网文档)
菜鸟教程bootstrap(速查手册)
这时候点击火焰按钮就可以弹出弹出层了,弹出之后页面会停滞一下,然后ajax刷新的数据就会填充弹出层。
火焰按钮:
modal弹出层:
创建表单 ActiveForm
把默认的检索表单注释掉之后,页面没有了搜索表单,现在我们手动添加搜索表单。
我们可以把表单空间使用下面的html结构组合起来。ActiveForm
的begin()
和end()
定义了表单的开始和结束。
<?php
use kartik\widgets\ActiveForm;
$model = new \frontend\models\StudentSearch();
$form = ActiveForm::begin([
'method'=>'get',
]);
?>
<div class=" panel panel-default">
<div class="form-inline"></div>
<div class="form-inline"></div>
</div>
<?php ActiveForm::end();?>
经过测试,下图中四个类都可以创建表单,不用纠结用哪个
我们添加下面的检索项目或组件:
- 姓名模糊查询
- 性别
- 年龄
- 入学日期区间
- 出生日期区间
- 搜索按钮
添加搜索控件
这里把用到的表单方法写出来。
下面的代码用到了:
\frontend\models\StudentSearch
模型kartik\widgets\*
包的高级控件yii\helpers\Html
助手kartik\widgets\ActiveForm
方法创建的$form
表单对象。
参考文档:
关于kartik
包的使用方法请拉到页面顶端查看文档链接,虽然都是英文,但是有示例以及对应代码。ActiveForm
常用内置组件 yii2.0 Activeform表单部分组件使用方法yii\helpers\Html
Html 帮助类
echo $form->field($model,'name')->textInput()->label('姓名:');
echo $form->field($model,'sex')->dropDownList([
''=>'-',
'0'=>'女',
'1'=>'男'
])->label('性别:');
use kartik\widgets\RangeInput;
echo $form->field($model,'age')->widget(RangeInput::className(),[
'html5Options' => ['min' => 0, 'max' => 30, 'step' => 1],
])->label(false);
use kartik\widgets\DatePicker;
echo DatePicker::widget(
[
'name' => Html::getInputName($model,'in_time_1'),
'value' => date('Y-m-d',time()-(3600*24*7)),
'type' => DatePicker::TYPE_RANGE,
'name2' => Html::getInputName($model,'in_time_2'),
'value2' => date('Y-m-d'),
'pluginOptions' => [
'autoclose'=>true,
'format' => 'yyyy-mm-dd'
]
]
);
echo DatePicker::widget(
[
'name' => Html::getInputName($model,'born_time_1'),
'value' => '',
'type' => DatePicker::TYPE_RANGE,
'name2' => Html::getInputName($model,'born_time_2'),
'value2' => '',
'pluginOptions' => [
'autoclose'=>true,
'format' => 'yyyy-mm-dd'
]
]
);
表单中控件的name属性:Html::getInputName()
方法的作用为,获取指定模型对象的表单name
值,例如\frontend\models\StudentSearch
模型的age
年龄属性的表单name
值应该为StudentSearch[sex]
。
表单中的输入框,下拉菜单,等等表单的name
,是用模型名[属性名]
来命名的。
在上面生成表单的时候,使用的Html::getInputName($model,'in_time_1')
方法的作用就是返回StudentSearch[in_time_1]
,所以直接把这个文本写在相同地方可以达到相同的效果。但是为了之后重构的方便,使用这样的方式可以避免修改模型名称的时候修改代码。
使用kartik的两种方法:
一些特殊的方法只能使用上面日期类型的方式使用kartik
,因为这一个方法输出了两个表单,或者是我的用法不对,如果有知道的同学,还请教。
其他常规的方法都有两种调用方式,各有优劣。
举个例子,上面年龄的写法,可以用下面两种方法。
echo $form->field($model,'age')->widget(RangeInput::className(),[
'html5Options' => ['min' => 0, 'max' => 30, 'step' => 1],
])->label(false);
echo RangeInput::widget([
'name'=>Html::getInputName($model,'age'),
'html5Options' => ['min' => 0, 'max' => 30, 'step' => 1],
]);
上面这两种方法都可以生成可用的表单,但是很多细节是不一样的。
第一种:
可以自动验证表单的正确性,如图:
包裹控件的div
的class
为input-group input-group-html5
,效果就是更加美观。
第二种:
代码更简洁。
添加完表单的组件之后,进行了一些css调整,现在的界面是这样的。
这些表单的组件,姓名,性别,年龄可以直接使用,因为在\frontend\models\StudentSearch.php
中已经写好方法,而两个时间的筛选需要自己写。
编写搜索模型 Models
ActiveDataProvider
打开\frontend\models\StudentSearch.php
,找到search
方法。
填充数据到几十条,用于测试分页,经过测试发现默认情况一页的数据是20条,GridView
自带了分页组件。
在创建ActiveDataProvider
的数组中添加一个'pagination' => ['pageSize' => 10,],
,改成下面这样,分页的数据就变成10条了。
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => ['pageSize' => 10,],
]);
在ActiveDataProvider
还可以添加排序等其他属性。
如果想要添加一个导出csv的方法,并且要使用搜索条件来导出指定数据,就可以使用ActiveDataProvider
中的getModels()
方法。当然我更建议使用扩展来解决导出csv的问题,参考http://demos.krajee.com/export
$models = $dataProvider->getModels();//获得model对象
$dataProvider->query->asArray()->all();//获得数组
搜索条件
在search
模型添加下面的成员,就是表单中的4个name。
public $in_time_1;
public $in_time_2;
public $born_time_1;
public $born_time_2;
在search
方法中添加下面代码,更多查询方法参考附录。
$query->andFilterWhere(['>=', 'in_time', $this->in_time_1?strtotime($this->in_time_1):'']);
$query->andFilterWhere(['<=', 'in_time', $this->in_time_2?strtotime($this->in_time_2):'']);
$query->andFilterWhere(['>=', 'born_time', $this->born_time_1]);
$query->andFilterWhere(['<=', 'born_time', $this->born_time_2]);
andFilterWhere()
可以看作是只用于搜索的一个方法,条件为空会忽略条件。
其他更多方法参考附录。
附录
注册js加载位置常量
$this->registerJs(string js代码,int 输出位置)
以下为yii\web\View
类的内置常量。
View::POS_HEAD
head标签末尾加载,无包裹JSView::POS_BEGIN
body标签头部加载,无包裹JSView::POS_END
body标签末尾加载,无包裹JSView::POS_READY
这是默认值,会把js注册到jQuery(document).ready(function () {});
View::POS_LOAD
会注册到jQuery(window).on('load', function () {});
数据库操作汇总
参考:http://blog.csdn.net/xundh/article/details/45955195/
//1.简单查询
$admin=Admin::model()->findAll($condition,$params);
$admin=Admin::model()->findAll("username=:name",array(":name"=>$username));
$infoArr= NewsList::model()->findAll("status = '1' ORDER BY id DESC limit 10 ");
//2. findAllByPk(该方法是根据主键查询一个集合,可以使用多个主键)
$admin=Admin::model()->findAllByPk($postIDs,$condition,$params);
$admin=Admin::model()->findAllByPk($id,"name like :name and age=:age",array(':name'=>$name,'age'=>$age));
$admin=Admin::model()->findAllByPk(array(1,2));
//3.findAllByAttributes (该方法是根据条件查询一个集合,可以是多个条件,把条件放到数组里面)
$admin=Admin::model()->findAllByAttributes($attributes,$condition,$params);
$admin=Admin::model()->findAllByAttributes(array('username'=>'admin'));
//4.findAllBySql (该方法是根据SQL语句查询一个数组)
$admin=Admin::model()->findAllBySql($sql,$params);
$admin=Admin::model()->findAllBySql("select * from admin where username like :name",array(':name'=>'%ad%'));
User::find()->all(); 此方法返回所有数据;
User::findOne($id); 此方法返回 主键 id=1 的一条数据(举个例子);
User::find()->where(['name' => '小伙儿'])->one(); 此方法返回 ['name' => '小伙儿'] 的一条数据;
User::find()->where(['name' => '小伙儿'])->all(); 此方法返回 ['name' => '小伙儿'] 的所有数据;
User::find()->orderBy('id DESC')->all(); 此方法是排序查询;
User::findBySql('SELECT * FROM user')->all(); 此方法是用 sql 语句查询 user 表里面的所有数据;
User::findBySql('SELECT * FROM user')->one(); 此方法是用 sql 语句查询 user 表里面的一条数据;
User::find()->andWhere(['sex' => '男', 'age' => '24'])->count('id'); 统计符合条件的总条数;
User::find()->one(); 此方法返回一条数据;
User::find()->all(); 此方法返回所有数据;
User::find()->count(); 此方法返回记录的数量;
User::find()->average(); 此方法返回指定列的平均值;
User::find()->min(); 此方法返回指定列的最小值 ;
User::find()->max(); 此方法返回指定列的最大值 ;
User::find()->scalar(); 此方法返回值的第一行第一列的查询结果;
User::find()->column(); 此方法返回查询结果中的第一列的值;
User::find()->exists(); 此方法返回一个值指示是否包含查询结果的数据行;
User::find()->batch(10); 每次取 10 条数据
User::find()->each(10); 每次取 10 条数据, 迭代查询
二、查询对象的方法
//根据主键查询出一个对象,如:findByPk(1);
$admin=Admin::model()->findByPk($postID,$condition,$params);
$admin=Admin::model()->findByPk(1);
//根据一个条件查询出一组数据,可能是多个,但是他只返回第一行数据
$row=Admin::model()->find($condition,$params);
$row=Admin::model()->find('username=:name',array(':name'=>'admin'));
//该方法是根据条件查询一组数据,可以是多个条件,把条件放到数组里面,查询的也是第一条数据
$admin=Admin::model()->findByAttributes($attributes,$condition,$params);
$admin=Admin::model()->findByAttributes(array('username'=>'admin'));
//该方法是根据SQL语句查询一组数据,他查询的也是第一条数据
$admin=Admin::model()->findBySql($sql,$params);
$admin=Admin::model()->findBySql("select * from admin where username=:name",array(':name'=>'admin'));
//拼一个获得SQL的方法,在根据find查询出一个对象
$criteria=newCDbCriteria;
$criteria->select='username';// only select the 'title' column
$criteria->condition='username=:username'; //请注意,这是一个查询的条件,且只有一个查询条件.多条件用addCondition
$criteria->params=array(":username=>'admin'");
$criteria->order ="id DESC";
$criteria->limit ="3";
$post=Post::model()->find($criteria);// $params isnot needed
//多条件查询的语句
$criteria= new CDbCriteria;
$criteria->addCondition("id=1");//查询条件,即where id = 1
$criteria->addInCondition('id',array(1,2,3,4,5));//代表where id IN (1,2,3,4,5,);
$criteria->addNotInCondition('id',array(1,2,3,4,5));//与上面正好相法,是NOT IN
$criteria->addCondition('id=1','OR');//这是OR条件,多个条件的时候,该条件是OR而非AND
$criteria->addSearchCondition('name','分类');//搜索条件,其实代表了。。where name like '%分类%'
$criteria->addBetweenCondition('id', 1, 4);//between 1 and 4
$criteria->compare('id', 1); //这个方法比较特殊,他会根据你的参数自动处理成addCondition或者addInCondition.
$criteria->compare('id',array(1,2,3)); //即如果第二个参数是数组就会调用addInCondition
$criteria->select ='id,parentid,name';//代表了要查询的字段,默认select='*';
$criteria->join ='xxx'; //连接表
$criteria->with ='xxx'; //调用relations
$criteria->limit = 10; //取1条数据,如果小于0,则不作处理
$criteria->offset = 1; //两条合并起来,则表示 limit 10 offset 1,或者代表了。limit 1,10
$criteria->order ='xxx DESC,XXX ASC' ;//排序条件
$criteria->group ='group 条件';
$criteria->having ='having 条件 ';
$criteria->distinct = FALSE;//是否唯一查询
三、查询个数,判断查询是否有结果
//该方法是根据一个条件查询一个集合有多少条记录,返回一个int型数字
$n=Post::model()->count($condition,$params);
$n=Post::model()->count("username=:name",array(":name"=>$username));
//该方法是根据SQL语句查询一个集合有多少条记录,返回一个int型数字
$n=Post::model()->countBySql($sql,$params);
$n=Post::model()->countBySql("select * from admin where username=:name",array(':name'=>'admin'));
//该方法是根据一个条件查询查询得到的数组有没有数据,如果有数据返回一个true,否则没有找到
$exists=Post::model()->exists($condition,$params);
$exists=Post::model()->exists("name=:name",array(":name"=>$username));
四、新增
$admin= new Admin;
$admin->username =$username;
$admin->password =$password;
if($admin->save() > 0){echo "添加成功"; }else{echo "添加失败"; }
五、修改
Post::model()->updateAll($attributes,$condition,$params);
$count=Admin::model()->updateAll(array('username'=>'11111','password'=>'11111'),'password=:pass',array(':pass'=>'1111a1'));
if($count> 0){ echo "修改成功"; }else{echo "修改失败"; }
$rt= PostList::model()->updateAll(array('status'=>'1'),'staff_id=:staff AND host_id=:host',array(':staff'=>$staff_id,':host'=>$host_id));
//$pk主键,可以是一个也可以是一个集合,$attributes是要修改的字段的集合,$condition条件,$params传入的值
Post::model()->updateByPk($pk,$attributes,$condition,$params);
$count=Admin::model()->updateByPk(1,array('username'=>'admin','password'=>'admin'));
$count=Admin::model()->updateByPk(array(1,2),array('username'=>'admin','password'=>'admin'),'username=:name',array(':name'=>'admin'));
if($count>0){echo "修改成功"; }else{echo "修改失败"; }
Post::model()->updateCounters($counters,$condition,$params);
$count=Admin::model()->updateCounters(array('status'=>1),'username=:name',array(':name'=>'admin'));
if($count> 0){ echo "修改成功"; }else{echo "修改失败"; }
//array('status'=>1)代表数据库中的admin表根据条件username='admin',查询出的所有结果status字段都自加1
六、删除
//deleteAll
Post::model()->deleteAll($condition,$params);
$count= Admin::model()->deleteAll('username=:name and password=:pass',array(':name'=>'admin',':pass'=>'admin'));
$count= Admin::model()->deleteAll('id in("1,2,3")');//删除id为这些的数据
if($count>0){echo"删除成功"; }else{echo "删除失败"; }
//deleteByPk
Post::model()->deleteByPk($pk,$condition,$params);
$count= Admin::model()->deleteByPk(1);
$count=Admin::model()->deleteByPk(array(1,2),'username=:name',array(':name'=>'admin'));
if($count>0){echo "删除成功"; }else{echo "删除失败"; }
2 条评论
棒棒棒
王天风是伪装者的王天风吗