阿江 2017-10-15 07:49:17 5785次浏览 0条回复 5 3 0

说明

学习Yii Framework 2易2框架的过程是漫长的也是充满乐趣的以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现提供了较完整的代码供你参考不妥之处请多多指正

原文网址:

http://www.yiiframework.com/doc-2.0/guide-output-data-widgets.html

本文主题:数据小部件(Data widgets)

Yii提供了一组小部件,它们可以用于显示数据。DetailView小部件可以用于显示一条记录的数据,ListView和GridView可以用于将数据显示为一个列表或表格,且可以实现分页、排序和筛选的功能。

1、DetailView(详情视图)

DetailView小部件显示一条记录的详细信息。它常用于以特定格式显示一个模型(例如:模型的每个属性显示为表格的一行)。模型可以是yii\base\Model或其子类(如Active Record)的实例,也可以是一个关联数组。

DetailView使用$attributes 属性来决定哪一个模型列将被显示出来,也会定义它们的显示格式,有效的格式化参数请参考formatter章节: http://www.yiiframework.com/doc-2.0/guide-output-formatting.html

DetailView典型用法如下例所示:

echo DetailView::widget([
    'model' => $model,
	//attributes
    'attributes' => [
        'title',                                           // title列(纯文本)
        'description:html',                                //description列格式化为HTML
		[
			'attribute' => 'tags',
			'value' => function ($model) {
				return implode(',',array_column($model->tags,'tag'));
			},
		],
        [                                                  //模型的ower name列
            'label' => 'Owner',
            'value' => $model->owner->name,            
            'captionOptions' => ['tooltip' => 'Tooltip'],  //label的HTML标签添加自定义属性<th tooltip="Tooltip">Owner</th>
			'contentOptions' => ['class' => 'text-right'],  //value的HTML标签添加自定义属性<td class="text-right">Asia</td>
            'visible' => false,//不显示此属性
//          'visible' => true,//显示此属性,默认值
        ],
		[
			//关联属性
			'attribute'=> 'user.nickname',
			'label'=>'Creater',
			'value'=>function($model){
				//获取关联属性的值
				return $model['user']['nickname']." ".date("Y年n月j日 H:i:s",$model->createdAt);
			},
			'visible' => \Yii::$app->user->can('updatePost', ['post' => $model]),
		],
		//显示标签
		[
			'label' => 'All Tags',
			'value' => function ($model) {
				return implode(',',array_column($model->tags,'tag'));
			},
		],
        [
            'attribute' => 'owner',
            'value' => function ($model) {
                return $model->owner->name;
            },
            'visible' => \Yii::$app->user->can('posts.owner.view'),
        ],
        [                                                  //模型的ower name列
            'label' => 'Owner',
            'value' => $model->owner->name,            
            'captionOptions' => ['tooltip' => 'Tooltip'],  //label的HTML标签添加自定义属性<th tooltip="Tooltip">Owner</th>
			'contentOptions' => ['class' => 'text-right'],  //value的HTML标签添加自定义属性<td class="text-right">Asia</td>
            'visible' => false,//不显示此属性
//          'visible' => true,//显示此属性,默认值
        ],
        'created_at:datetime',                             // creation date formatted as datetime
    ],
]);

记住:与yii\grid\GridView(原文档中是yii\widgets\GridView,错误!)处理一组模型不同,DetailView只处理一个模型。因为$model 是唯一的一个要在视图中有效并显示的模型,所以大多数时候无需使用闭包函数。 但有时也会使用到闭包函数,例如:当定义visible时,如果当此列的值为false时,你不想让它参与计算,就需要使用闭包函数了。

echo DetailView::widget([
    'model' => $model,
    'attributes' => [
        [
            'attribute' => 'owner',
            'value' => function ($model) {
                return $model->owner->name;
            },
            'visible' => \Yii::$app->user->can('posts.owner.view'),
        ],
    ],
]);
2、ListView(列表视图)

ListView小部件用于显示data provider提供的数据。每个数据模型使用一个特定的视图文件进行渲染。因为它提供了如分页、排序和筛选等特性,它被用于向终端用户显示信息或用于创建数据管理的UI。

一个典型用法如下例所示:

use yii\widgets\ListView;
use yii\data\ActiveDataProvider;

$dataProvider = new ActiveDataProvider([
    'query' => Post::find(),
    'pagination' => [
        'pageSize' => 20,
    ],
]);
echo ListView::widget([
    'dataProvider' => $dataProvider,
    'itemView' => '_post',
	'layout' => '{pager}{summary}{items}{summary}{pager}',//列表前后位置都显示翻页按钮和汇总信息
]);

_post视图文件包括以下内容:

<?php
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;
?>
<div class="post">
    <h2><?= Html::encode($model->title) ?></h2>

    <?= HtmlPurifier::process($model->text) ?>    
</div>

在这个视图文件中,当前的数据模型被定义为$model ,另外还有一些变量也可以被使用:

$key ,混合类型,与数据项相关联的键名
$index ,整型,数据提供者返回的数据项索引号,从0开始
$widget ,ListView类型,widget实例

如果你需要为视图传递更多的数据,你可以使用$viewParams 属性来定义键值对,代码如下:

echo ListView::widget([
    'dataProvider' => $dataProvider,
    'itemView' => '_post',
    'viewParams' => [
        'fullView' => true,
        'context' => 'main-page',
        // ...
    ],
]);

$viewParams 中的键值对在视图中可以直接作为变量来引用。

ListView实例:

D:\phpwork\basic\controllers\CountryController.php

    public function actionList() {
        return $this->render("list");
    }

D:\phpwork\basic\views\country\list.php

<?php
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
$dataProvider=new ActiveDataProvider([
	'query'=>\app\models\Country::find(),
	'pagination'=>[
		'pageSize'=>2,
	],
]);
echo ListView::widget([
	'dataProvider'=>$dataProvider,
	'itemView'=>'_list',
	'viewParams' => [
		'fullView' => true,
		'context' => 'main-page',
	],
]);

D:\phpwork\basic\views\country_list.php

<?php
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;
?>
<div class="post">
	<h2><?= Html::encode($model->name) ?></h2>
	<?= HtmlPurifier::process($model->population) ?>
	key:<?=$key?>
	index:<?=$index?>
	context:<?=$context?>
	<?
	//var_dump($widget);
	?>
</div>
测试结果:
http://localhost:8081/country/list?page=1&per-page=2
/*
Showing 1-2 of 8 items.
232233aabb
2245	key:58a14411e4017a1c16000029	index:0	context:main-page
china2
90	key:58aaad6a45940fd795f941b0	index:1	context:main-page
« 1 2 3 4 »
*/
3、GridView(网格视图)

数据格或GridView在Yii小部件中功能很强大,如果你要构建系统管理后台,使用它的地方会非常多。它从一个数据提供器(data provider)获取数据,并对每行数据进行渲染,渲染时是使用列设置将每个数据填充到表格单元。

表格中的每一行代表一条数据记录,列则代表记录的字段值(一些列可能会对应多字段的复杂表达式或静态文本)。 GridView的最小代码块如下所示:

use yii\grid\GridView;
use yii\data\ActiveDataProvider;
$dataProvider = new ActiveDataProvider([
    'query' => Post::find(),
    'pagination' => [
        'pageSize' => 20,
    ],
]);
echo GridView::widget([
    'dataProvider' => $dataProvider,
]);

以上代码先创建了一个数据提供器,然后使用Gridview显示每行的每个数据。显示的表格使用了排序和翻页功能。

实例,GridView基本实例

D:\phpwork\basic\controllers\BlogController.php

class BlogController extends Controller{
    public function actionIndex(){
        $dataProvider = new ActiveDataProvider([
            'query' => Blog::find(),
        ]);
        return $this->render('index', [
            'dataProvider' => $dataProvider,
        ]);
	}
}

D:\phpwork\basic\views\blog\index.php

<?php Pjax::begin(); ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'id',
            'title',
            'content:ntext',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
<?php Pjax::end(); ?></div>
网格列(Grid columns)

在GridView中可以配置columns属性,这些Grid表格列是以yii\grid\Column类的方式来配置的。根据这些列的类型和设置可以代表不同的数据。默认类是yii\grid\DataColumn,代表一个模型属性,可以排序和过滤。

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],
		//普通列使用$dataProvider中包含的列名来定义,数据将从模型的属性中获取。
        'id',
        'username',
		//更复杂的一个列定义
        [
            'class' => 'yii\grid\DataColumn', //默认值,可以省略
            'value' => function ($data) {
                return $data->name; //数组数据$data['name'],例如使用SqlDataProvider
            },
        ],
    ],
]);

注意如果配置中的columns未定义,Yii将尽可能的展现数据提供器模型中的数据列。

列类(Column classes)

网格列可以使用不同的列类来自定义:

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        [
            'class' => 'yii\grid\SerialColumn', 
			//在此你可以定义附加的属性
        ],

Yii提供了4种列类:数据列(Data column)、动作列(Action column)、复选框列(Checkbox column)、序号列(Serial column) 除了使用Yii提供的列类之外,你还要吧创建自己的列类,稍后你将看到这种况。 每个列类都扩展自yii\grid\Column,所以在配置网格列时,可以配置公共的选项: header,设置头行的内容 footer,设置尾行的内容 visible,定义该列是否可见 content,你可以传递一个PHP回调函数,它的返回值将作为行数据,格式为:

	function ($model, $key, $index, $column) {
		return 'a string';
	}

你可以使用数组定义不同的HTML容器选项: headerOptions footerOptions filterOptions contentOptions

数据列(Data column)

yii\grid\DataColumn 数据列用于显示和排序数据,它是默认的列类型,当使用这种类型时可以省略它。 数据列的主要设置是它的format属性,它的值对应于formatter应用组件中默认Formatter的方法:

echo GridView::widget([
    'columns' => [
        [
            'attribute' => 'name',
            'format' => 'text'
        ],
        [
            'attribute' => 'birthday',
            'format' => ['date', 'php:Y-m-d']
        ],
    ],
]);

如上代码所示,text对应于yii\i18n\Formatter::asText()方法。列值将被作为第1个参数传送过去。在第二个列定义中,date对应于yii\i18n\Formatter::asDate()方法。列值将被作为第1个参数,'php:Y-m-d'被作为第2个参数传送过去。 关于有效的格式化器请参见Data Formattin章节: http://www.yiiframework.com/doc-2.0/guide-output-formatting.html

在columns的API文档中有关于配置列的快捷格式: http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html#$columns-detail

动作列(Action column)

动作列显示动作按钮,如每行记录的更新或删除操作等。

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        [
            'class' => 'yii\grid\ActionColumn',
			//可以在这里配置附加的属性
        ],

你可以配置的附加属性是: 1、controller,操作这些动作的控制器ID,如果没有设置,将使用当前控制器。 2、template,定义动作列中每个单元格所使用的模板。在模型中,大括号包含的标签将作为控制器的动作ID(在动作列中也被称为按钮名称),它们将被定义在buttons中的闭包函数所替换,例如,标签{view}将被替换为buttons['view'],如果闭包函数没有找到,则标签将被替换成空字符串。默认的标签是{view} {update} {delete} 3、buttons,是一个数组,包含了按钮渲染的闭包函数。数组键名是按钮名称(没有大括号),键值是对应的按钮渲染闭包函数,此函数可以使用以下格式:

function ($url, $model, $key) {
    //返回按钮的HTML代码
}

在上述代码中,$url 是按钮指向的URL,$model 是当前行渲染的模型对象,$key 是数据提供器数组模型的键名。 4、urlCreater,是一个闭包函数,它使用模型的特定信息创建一个按钮URL,闭包函数的格式与yii\grid\ActionColumn::createUrl()相同,如果此属性没有设置,按钮的URL将使用yii\grid\ActionColumn::createUrl()创建。 5、visibleButtons,是一个数组,定义了每个按钮可以查看到的条件。数组键名是按钮名(没有大括号),键值是布尔型true/false或者是一个匿名函数。当按钮名在数据中没有定义,它将默认被显示出来,闭包函数须使用如下格式:

function ($model, $key, $index) {
    return $model->status === 'editable';
}

或者你也可以传递一个布尔值:

[
    'update' => \Yii::$app->user->can('update')
]
Action column实例://ActionColumn

D:\phpwork\news\views\articles\index.php

	//使用图标按钮,增加按钮间距,增加了权限判断
		[
			'header' => '操作',
			'class' => 'yii\grid\ActionColumn',
			'options'=>['style'=>'width: 100px;'],
			'buttons'=>[
				'view'=> function ($url, $model, $key) {
					$options = [
						'title' => Yii::t('app', 'View'),
						'aria-label' => Yii::t('app', 'View'),
						'data-pjax' => '0',
						'style'=>'padding:0 5px',
					];
					return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, $options);
				},
				'update'=> function ($url, $model, $key) {
					//使用权限判断
					if(\Yii::$app->user->can('updatePost', ['post' => $model])){
						$options = [
							'title' => Yii::t('app', 'Update'),
							'aria-label' => Yii::t('app', 'Update'),
							'data-pjax' => '0',
							'style'=>'padding:0 5px',
						];
						return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
					}
				},
				'delete'=> function ($url, $model, $key) {
					if(\Yii::$app->user->can('updatePost', ['post' => $model])){
						$options = [
							'title' => Yii::t('app', 'Delete'),
							'aria-label' => Yii::t('app', 'Delete'),
							'data-pjax' => '0',
							'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
							'style'=>'padding:0 5px',
						];
						return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, $options);
					}
				},
			],
		],

D:\phpwork\basic\views\country\grid.php

	//使用文字链接
		[
			'header' => 'Operations',
			'class' => 'yii\grid\ActionColumn',
			'options'=>['style'=>'width: 250px;'],
			'buttons'=>[
				'view'=> function ($url, $model, $key) {
					$options = [
						'title' => Yii::t('app', 'View'),
						'aria-label' => Yii::t('app', 'View'),
						'data-pjax' => '0',
						'class'=>'btn btn-circle btn-icon-only blue',
					];
					return Html::a('View', $url, $options);
				},
				'update'=> function ($url, $model, $key) {
					$options = [
						'title' => Yii::t('app', 'Update'),
						'aria-label' => Yii::t('app', 'Update'),
						'data-pjax' => '0',
						'class'=>'btn btn-circle btn-icon-only green',
					];
					return Html::a('Update', $url, $options);
				},
				'delete'=> function ($url, $model, $key) {
					$options = [
						'title' => Yii::t('app', 'Delete'),
						'aria-label' => Yii::t('app', 'Delete'),
						'data-pjax' => '0',
						'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
						'class'=>'btn btn-circle btn-icon-only red',
					];
					return Html::a('Delete', $url, $options);
				},
			],
		],

<span class="glyphicon glyphicon-eye-open"></span>
<span class="glyphicon glyphicon-pencil"></span>
<span class="glyphicon glyphicon-trash"></span>
复选框列(Checkbox column)

复选框列显示了一列复选框。 要为GridView添加一个CheckboxColumn,需要在columns中进行如下配置:

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        // ...
        [
            'class' => 'yii\grid\CheckboxColumn',
			//添加其他配置项
        ],
    ],

用户可以在复选框上点击以选中网格的一行,要获取选中的行可以在JavaScript代码中调用以下代码:

var keys=$('#grid').yiiGridView('getSelectedRows');
//keys是与选定行相关联键名的数组。

//序号列(Serial column)
序号列显示了每一行的行号,从1开始计数。
使用示例如下:
echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'], // <-- here
        // ...
数据排序(Sorting data)
数据过滤(Filtering data)

要实现数据过滤,网格需要一个具有搜索标准的模型,它会从GridView表格中获取过滤项。使用Active Record的一个最佳实践是创建一个搜索模型类,使用它提供必需的功能(可以使用Gii生成它),这个类定义了GridView表格过滤项的验证规则,提供了一个search()方法,它将使用搜索关键字生成特定查询,并返回一个数据提供器。 要为Post模型添加搜索功能,我们可以使用以下代码创建一个PostSearch模型:

<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class PostSearch extends Post
{
    public function rules()
    { 
        // only fields in rules() are searchable
        return [
            [['id'], 'integer'],
            [['title', 'creation_date'], 'safe'],
        ];
    }

    public function scenarios()
    {
		//使用Model的默认场景,从而跳过父类Post的场景
        return Model::scenarios();
    }

    public function search($params)
    {
        $query = Post::find();

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        // load the search form data and validate
        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }

        // adjust the query by adding the filters
        $query->andFilterWhere(['id' => $this->id]);
        $query->andFilterWhere(['like', 'title', $this->title])
              ->andFilterWhere(['like', 'creation_date', $this->creation_date]);

        return $dataProvider;
    }
}

小贴士:如何构建查询语句请查看Query Builder中的Filter Conditions部分: http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html#filter-conditions

你可以在控制器中使用此方法为GridView获取数据提供器(Data Provider):

$searchModel=new PostSearch();
$dataProvider=$searchModel->search(Yii::$app->request->get());
return $this->render('myview',[
	'dataProvider'=>$dataProvider,
	'searchModel'=>$searchModel,
]);

在视图中你可以填充$dataProvider 和$searchModel 到GridView中去:

echo GridView::widget([
	'dataProvider'=>$dataProvider,
	'filterModel'=>$searchModel,
	'columns'=>[
		//...	
	],
]);
实例,数据过滤实例,单独过滤器表单实例

D:\phpwork\basic\controllers\BlogController.php

namespace app\controllers;
use Yii;
use app\models\Blog;
use app\models\BlogSearch;
class BlogController extends Controller
{
    public function actionIndex()
    {
        $filterModel=new BlogSearch();
        $dataProvider=$filterModel->search(Yii::$app->request->get());
        return $this->render('index',[
            'dataProvider'=>$dataProvider,
            'filterModel'=>$filterModel,
        ]);
    }
}

D:\phpwork\basic\models\Blog.php

<?php
namespace app\models;
use Yii;
/**
 * This is the model class for table "blog".
 *
 * @property string $id
 * @property string $title
 * @property string $content
 */
class Blog extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'blog';
    }
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['content'], 'string'],
            [['title'], 'string', 'max' => 50],
        ];
    }
    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'title' => Yii::t('app', 'Title'),
            'content' => Yii::t('app', 'Content'),
        ];
    }
    /**
     * @inheritdoc
     * @return BlogQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new BlogQuery(get_called_class());
    }
	//beforeSave
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if($insert){
                $this->create_at=time();
            }
            $this->update_at=time();
            return true;
        } else {
            return false;
        }
    }
}

D:\phpwork\basic\models\BlogSearch.php

<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class BlogSearch extends Blog
{
    public $createdFrom;
    public $createdTo;
    public function rules()
    {
        // only fields in rules() are searchable
        return [
            [['_id','title', 'content','createdFrom','createdTo'], 'safe'],

        ];
    }
    public function scenarios()
    {
		//使用Model的默认场景,从而跳过父类Blog的场景
        return Model::scenarios();
    }
    public function search($params){
        $query = Blog::find();
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 20,
            ],
        ]);
        // load the search form data and validate
        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }
        $createdFrom=($this->createdFrom!="")?strtotime($this->createdFrom):"";
        $createdTo=($this->createdTo!="")?strtotime($this->createdTo):"";
        // adjust the query by adding the filters
        $query->andFilterWhere(['like', 'title', $this->title])
            ->andFilterWhere(['like', 'content', $this->content]);
        $query->andFilterWhere(['>=', 'create_at', $createdFrom])
            ->andFilterWhere(['<=', 'create_at', $createdTo]);
        return $dataProvider;
    }
}

D:\phpwork\basic\views\blog\index.php

<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
/* @var $this yii\web\View */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Blogs';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="blog-index">
    <h1><?= Html::encode($this->title) ?></h1>
    <p>
        <?= Html::a('Create Blog', ['create'], ['class' => 'btn btn-success']) ?>
    </p>
<?php Pjax::begin(); ?>
    <?= $this->render('_search', ['model' => $filterModel]) ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $filterModel,
		//columns
        'columns' => [
            [
                'class' => 'yii\grid\SerialColumn',
            ],
            'id',
            'title',
            'content',
            'content:ntext',
			//简写格式:attribute:format:label
			'amount:currency:Total Amount',
			//对content进行格式转换
            [
                'attribute' => 'content',
                'value' => function ($model) {
                    if($model->format==1){
                        return $model->content;
                    }else{
                        return Markdown::convert($model->content);
                    }
                },
                'format'=>'text',
            ],
			//create_at
            [			
                'attribute' => 'create_at',
				'value' => function ($model,$key,$index, $column) {
					//$model,当前的模型;$key,当前记录的键名;$index,当前记录的索引;$column,当前列的配置(是一个DataColumn对象)
					return date("Y-n-j",$model->create_at).',key:'.$key.',index:'.$index.',columnAttribute:'.$column->attribute;
					//第3条记录的返回值:2017-3-24,key:3,index:2,columnAttribute:create_at
				},
            ],
            [
                'class' => 'yii\grid\ActionColumn',
            ],
        ],
    ]); ?>
<?php Pjax::end(); ?></div>

<? D:\phpwork\basic\views\blog_search.php

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model app\models\PostSearch */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="post-search">
    <?php $form = ActiveForm::begin([
        'action' => ['index'],
        'method' => 'get',
    ]); ?>
    <?= $form->field($model, 'title') ?>
    <?= $form->field($model, 'content') ?>
    <?= $form->field($model, 'createdFrom')->textInput(['type'=>"date"]) ?>
<!--<input type="date" id="blogsearch-createdfrom" class="form-control" name="BlogSearch[createdFrom]"> -->
    <?= $form->field($model, 'createdTo')->textInput(['type'=>"date"]) ?>
    <div class="form-group">
        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
        <?= Html::submitButton('Reset', ['class' => 'btn btn-default']) ?>
    </div>
    <?php ActiveForm::end(); ?>
</div>
单独的过滤器表单

大多数情况下使用GridView头部过滤器就足够了,但有时你可能还需要一个单独的过滤器表单,你可以很容易就把它添加上。你可以创建一个局部视图(partial view)文件_search.php,代码如下:

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model app\models\PostSearch */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="post-search">
    <?php $form = ActiveForm::begin([
        'action' => ['index'],
        'method' => 'get',
    ]); ?>
    <?= $form->field($model, 'title') ?>
    <?= $form->field($model, 'creation_date') ?>
    <div class="form-group">
        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
        <?= Html::submitButton('Reset', ['class' => 'btn btn-default']) ?>
    </div>
    <?php ActiveForm::end(); ?>
</div>

<? 在index视图中添加_search.php

<?= $this->render('_search', ['model' => $searchModel]) ?>

注意:如果你是使用Gii生成的CRUD代码,默认情况下单独过滤器表单(_search.php)已经生成好了,仅仅是在index.php视图中被注释掉了而已,将注释去掉就可以使用了。

当你使用不在GridView中显示的字段或对特殊条件过滤时,单独过滤器表单就非常有用了。要过滤日期范围,我们可以添加非数据库属性createFrom和createTo到搜索模型:

class PostSearch extends Post
{
    /**
     * @var string
     */
    public $createdFrom;

    /**
     * @var string
     */
    public $createdTo;
}

在search()方法中扩展查询条件如下所示:

$query->andFilterWhere(['>=', 'creation_date', $this->createdFrom])
      ->andFilterWhere(['<=', 'creation_date', $this->createdTo]);

然后添加相应字段到过滤表单中:

<?= $form->field($model, 'creationFrom') ?>
<?= $form->field($model, 'creationTo') ?>
操作关联模型(Working with model relations)

在GridView中显示活动记录(active records)时,你或许会感到这种情况,在显示作者列时,你想要显示的是作者的姓名,而不是他的id。要实现这个目标,你只需在yii\grid\GridView::$columns 中定义属性名称为author.name即可,当然,首先需要在Post模型中存在与author模型的关联,并且在author模型中有一个name属性。GridView将显示作者名称,但是默认情况下对这个字段是无法进行排序和过滤筛选的。你可以调整上节中介绍的PostSearch模型添加这两项功能。 要对关联列排序,你需要添加关联表并添加排序规则到数据提供器的排序组件中去:

$query = Post::find();
$dataProvider = new ActiveDataProvider([
    'query' => $query,
]);
//与author关联的表是user,并设置author表的别名是 author
// and set the table alias to be `author`
$query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
//从 2.0.7版本开始,上一行代码可以简写为$query->joinWith('author AS author')
//使关联列排序生效
$dataProvider->sort->attributes['author.name'] = [
    'asc' => ['author.name' => SORT_ASC],
    'desc' => ['author.name' => SORT_DESC],
];
// ...

过滤操作也如上例一样需要使用joinWith调用,你也需要定义列的搜索功能和规则,代码如下:

public function attributes()
{
    // add related fields to searchable attributes
    return array_merge(parent::attributes(), ['author.name']);
}

public function rules()
{
    return [
        [['id'], 'integer'],
        [['title', 'creation_date', 'author.name'], 'safe'],
    ];
}

然后在search()中你添加一个过滤条件:

$query->andFilterWhere(['LIKE', 'author.name', $this->getAttribute('author.name')]);

信息:在上例中,我们为表别名和关联名称都使用的是相同的名称,当你的别名和关联名不相同时,你要注意别名和关联名的所用之处。一个简单规律是在每个需要构建数据库查询的地方使用别名,在其他地方,如attributes()和rules()等地方都使用关联名称。

例如,你为关联表author使用别名au,joinWith语句就是这样:

$query->joinWith(['author au']);

当别名定义在关联定义中,则会使用到如下调用:

$query->joinWith(['author']);

别名用于过滤条件,但是属性名称中要保持原样:

$query->andFilterWhere(['like','au.name',$this->getAttribute('author.name')]);

排序的定义也是同样的道理:

$dataProvider->sort->attributes['author.name'] = [
     'asc' => ['au.name' => SORT_ASC],
     'desc' => ['au.name' => SORT_DESC],
];

在定义默认排序时,你需要使用关联名称而不能使用别名:

$dataProvider->sort->defaultOrder = ['author.name' => SORT_ASC];

信息:关于joinWith和后台查询性能的更多信息,请查看“active record docs on joining with relations”文档: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations

实例,在GridView的查询中使用关联属性别名//relationGridView

// GridView默认是按作者反向排序,可以在页面表格中对作者排序进行更改 D:\phpwork\basic\controllers\BlogController.php

class BlogController extends Controller
{
    public function actionIndex()
    {
        $filterModel=new BlogSearch();
        $dataProvider=$filterModel->search(Yii::$app->request->get());
        //设置默认排序时要使用全称:author.name
        $dataProvider->sort->defaultOrder = ['author.name' => SORT_DESC];
        return $this->render('index',[
            'dataProvider'=>$dataProvider,
            'filterModel'=>$filterModel,
        ]);
    }

D:\phpwork\basic\models\BlogSearch.php

class BlogSearch extends Blog
{
    public function search($params){
        $query = Blog::find();
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 20,
            ],
        ]);
        $query->joinWith(['author au']);
        //$query->joinWith(['author as au']);//与上句等效
        //别名au只能在sql语句中使用,在获取属性时还要使用全称author.name
        $dataProvider->sort->attributes['author.name'] = [
            'asc' => ['au.name' => SORT_ASC],
            'desc' => ['au.name' => SORT_DESC],
        ];
        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }
        $createdFrom=($this->createdFrom!="")?strtotime($this->createdFrom):"";
        $createdTo=($this->createdTo!="")?strtotime($this->createdTo):"";
        $query->andFilterWhere(['like', 'title', $this->title])
            ->andFilterWhere(['like', 'content', $this->content]);
        $query->andFilterWhere(['>=', 'create_at', $createdFrom])
            ->andFilterWhere(['<=', 'create_at', $createdTo]);
        //别名au只能在sql语句中使用,在获取属性时还要使用全称author.name
        $query->andFilterWhere(['LIKE', 'au.name', $this->getAttribute('author.name')]);
        return $dataProvider;
    }

D:\phpwork\basic\models\Blog.php

<?php
namespace app\models;
use Yii;
/**
 * This is the model class for table "blog".
 *
 * @property string $id
 * @property string $title
 * @property string $content
 */
class Blog extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'blog';
    }
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['content'], 'string'],
            [['title'], 'string', 'max' => 50],
            [$this->attributes(),'safe'],
        ];
    }
    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'title' => Yii::t('app', 'Title'),
            'content' => Yii::t('app', 'Content'),
            'author.name'=>'作者',
        ];
    }
    /**
     * @inheritdoc
     * @return BlogQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new BlogQuery(get_called_class());
    }
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if($insert){
                $this->create_at=time();
            }
            $this->update_at=time();
            return true;
        } else {
            return false;
        }
    }

    public function getAuthor() {
        return $this->hasOne(Author::className(), ['id' => 'authorid']);
    }

}

D:\phpwork\basic\config\web.php

<?php
$params = require(__DIR__ . '/params.php');
$db = require(__DIR__ . '/db-local.php');
$mongodb = require(__DIR__ . '/mongodb-local.php');
$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'components' => [
        'db' => $db,
        'mongodb' => $mongodb,
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'xinxZ50CwklfrgV3ORZfEgoWQIqUEtlm',
        ],
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        //prettyUrl,//urlManager
        'urlManager' => [
            'class' => 'yii\web\UrlManager',
            'showScriptName' => false,
            'enablePrettyUrl' => true,
            'rules' => array(
				//mongoDB的详情页地址:http://localhost:8082/country/view/58899feae4017a740c000029
				'<controller:\w+>/view/<id:\w+>' => '<controller>/view',
                //'<controller:\w+>/<id:\d+>' => '<controller>/view',//mysql详情页的写法
                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
            ),
			//D:\phpwork\b2b\imall\frontend\config\main.php
            'rules' => array(
                'site/<urlKey:.+>/productdetail' => 'site/productdetail',
                'promotion/<name:\w+>' => 'promotion/index',
                '<controller:\w+>/<id:\d+>' => '<controller>/view',
                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
            ),
        ],
        /*
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],
        */
    ],
    'modules' => [
        'admin' => [
            'class' => 'app\modules\admin\Module',
        ],
    ],
//    'language' => 'en',
    'language' => 'zh-CN',
    'params' => $params,
];

if (YII_ENV_DEV) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = [
        'class' => 'yii\debug\Module',
    ];

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = [
        'class' => 'yii\gii\Module',
    ];
}
return $config;
D:\phpwork\basic\config\db-local.php
<?php
return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=yiibasic',
    'username' => 'yiiuser',
    'password' => 'jkljl23asdf23oickxvzklqwer',
    'charset' => 'utf8',
];
D:\phpwork\basic\config\mongodb-local.php
<?php
return [
    'class' => 'yii\mongodb\Connection',
    'dsn' => 'mongodb://yiibaseuser:ycj123456@127.0.0.1:27017/yiibase',
];
使用SQL视图过滤、排序和显示数据(Using SQL views for filtering,sorting and displaying data)

有另外一种方法可以更快也更有效——SQL视图(views),例如,如果我们需要显示users和相关信息的GridView时,我们可以使用如下代码:

CREATE OR REPLACE VIEW vw_user_info AS
    SELECT user.*, user_profile.lastname, user_profile.firstname
    FROM user, user_profile
    WHERE user.id = user_profile.user_id

然后你需要创建ActiveRecord来展现这个SQL视图:

namespace app\models\views\grid;

use yii\db\ActiveRecord;

class UserView extends ActiveRecord
{

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'vw_user_info';
    }

    public static function primaryKey()
    {
        return ['id'];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            // define here your rules
        ];
    }

    /**
     * @inheritdoc
     */
    public static function attributeLabels()
    {
        return [
            // define here your attribute labels
        ];
    }
}

在search模型中你可以使用这个UserView AR模型,无需使用额外的排序和过滤属性定义,所有的属性都可以即选即用。注意使用此方法有以下优缺点: 1、你无需定义不同的排序和过滤条件,开箱即用; 2、因为数据量少,执行的SQL查询次数少,所以它的执行速度可以非常快(对于每个关联你无需进行额外的查询) 3、因为这仅是一个简单的SQL视图到UI的映射,缺少了在实际应用中的逻辑,所以如果你有一些方法,如isActive、isDeleted或其他将要影响UI的,你需要在类中复制它们。

实例,SQL视图实例

//创建SQL视图:

CREATE OR REPLACE VIEW view_author_info AS
    SELECT author.*, author_info.lastname, author_info.firstname
    FROM author, author_info
    WHERE author.id = author_info.authorid

D:\phpwork\basic\controllers\AuthorsqlController.php

use app\models\AuthorViewSearch;
class AuthorsqlController extends Controller
{
    public function actionIndexinfo()
    {
        $searchModel = new AuthorViewSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->sort->defaultOrder = ['name' => SORT_ASC];//定义默认排序方式
        return $this->render('indexinfo', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

D:\phpwork\basic\models\AuthorViewSearch.php

<?php
namespace app\models;

use Yii;
use yii\data\ActiveDataProvider;

class AuthorViewSearch extends AuthorView {
    public function rules() {
        return [//标记为safe的属性将在表格中显示搜索框
            [['name', 'firstname', 'lastname'], 'safe'],];
    }

    public function search($params) {
        $query = AuthorView::find();
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 20,//定义每页显示的记录数
            ],
        ]);
        $this->load($params);
        if (!$this->validate()) {
            return $dataProvider;
        }
        //添加查询筛选条件
        $query->andFilterWhere(['like', 'name', $this->name])->andFilterWhere(['like', 'firstname', $this->firstname])->andFilterWhere(['like', 'lastname', $this->lastname]);
        return $dataProvider;
    }
}

D:\phpwork\basic\views\authorsql\indexinfo.php

    <h1><?= Html::encode($this->title) ?></h1>
    <?php // echo $this->render('_search', ['model' => $searchModel]); ?>
    <p>
        <?= Html::a(Yii::t('app', 'Create Author'), ['create'], ['class' => 'btn btn-success']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('Blog List', ['/blog/index'], ['class' => 'btn btn-default']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('Author List', ['/authorsql/index'], ['class' => 'btn btn-default']) ?>
    </p>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'name',
            'firstname',
            'lastname',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
测试结果:
http://localhost:8081/authorsql/indexinfo
/*
AuthorsInfo
1	Bomer	Tang	Bomer	  
2	gulong	Gu	Long	  
3	jingyong	Jin	Yong	  
4	Johns	Xi	Johns	  
*/
在页面中使用多个GridView(Multiple GridViews on one page)

你可以在一个页面中使用多个GridView,但是需要你做一些配置,以避免它们相互干扰。当使用GridView的多实例时,你需要配置不同的排序和分页链接参数,这样每个GridView才能按照它自己的排序和分页正常操作。需要设置的是dataProvider的sort和pagination实例的排序参数(sortParam)和分页参数(pageParam)。 假定我们想要列出Post和User模型,我们已经准备好了两个数据提供器:$userProvider 和$postProvider :

use yii\grid\GridView;

$userProvider->pagination->pageParam = 'user-page';
$userProvider->sort->sortParam = 'user-sort';

$postProvider->pagination->pageParam = 'post-page';
$postProvider->sort->sortParam = 'post-sort';

echo '<h1>Users</h1>';
echo GridView::widget([
    'dataProvider' => $userProvider,
]);

echo '<h1>Posts</h1>';
echo GridView::widget([
    'dataProvider' => $postProvider,
]);
实例,在一个页面显示多个GridView实例,显示两个GridView//twoGridView

D:\phpwork\basic\controllers\AuthorsqlController.php

use Yii;
use app\models\AuthorSearch;
use app\models\BlogSearch;
class AuthorsqlController extends Controller
{
    public function actionMultiple()
    {
		//创建Author搜索模型实例
        $searchModel = new AuthorSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);//获取查询参数
		//配置Author的分页参数名称
        $dataProvider->pagination->pageParam = 'author-page';
		//配置Author的排序参数名称
        $dataProvider->sort->sortParam = 'author-sort';
        $dataProvider->pagination->pageSize = 1;//每页显示的记录数量

		//创建Blog搜索模型实例
        $blogModel=new BlogSearch();
        $blogProvider=$blogModel->search(Yii::$app->request->get());//获取查询参数的另外一种写法
		//配置Blog的分页参数名称
        $blogProvider->pagination->pageParam = 'blog-page';
		//配置Blog的排序参数名称
        $blogProvider->sort->sortParam = 'blog-sort';
        $blogProvider->pagination->pageSize = 2;
        return $this->render('multiple', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
            'blogProvider'=>$blogProvider,
            'blogModel'=>$blogModel,
        ]);
    }

D:\phpwork\basic\models\AuthorSearch.php

<?php
namespace app\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Author;

/**
 * AuthorSearch represents the model behind the search form about `app\models\Author`.
 */
class AuthorSearch extends Author
{
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id'], 'integer'],
            [['name'], 'safe'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
		//使用Model的默认场景,从而跳过直接父类的场景
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = Author::find();

        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
        ]);

        $query->andFilterWhere(['like', 'name', $this->name]);

        return $dataProvider;
    }
}

D:\phpwork\basic\models\Author.php

<?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "author".
 *
 * @property integer $id
 * @property string $name
 */
class Author extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'author';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name'], 'string', 'max' => 20],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'name' => Yii::t('app', 'Name'),
        ];
    }
    public function getBlogs(){
        return $this->hasMany(Blog::className(),['authorid'=>'id']);
    }

    public function getArticle() {
        return $this->hasMany(Articlesql::className(),['authorId'=>'id']);
    }
}

D:\phpwork\basic\models\BlogSearch.php

<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class BlogSearch extends Blog
{
    public $createdFrom;
    public $createdTo;
    public function attributes()
    {
        //添加关联属性到到可搜索列表中去,在GridView中才会出现作者的搜索框
        return array_merge(parent::attributes(), ['author.name']);
    }
    public function rules()
    {
        return [
			//只有在rules中的属性才能被搜索
            [['_id','title', 'content','createdFrom','createdTo','author.name'], 'safe'],
//            [$this->attributes(),'safe'],//使用此句更方便,可以实现更多字段的自动扩展
        ];
    }
    public function scenarios()
    {
		//使用Model的默认场景,从而跳过直接父类的场景
        return Model::scenarios();
    }
    public function search($params){
        $query = Blog::find();
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                'pageSize' => 20,
            ],
        ]);
        $query->joinWith(['author au']);//获取author关联属性,在GridView中才能引用author.name
        //$query->joinWith(['author as au']);//与上句等效
        //别名au只能在sql语句中使用,在获取属性时还要使用全称author.name
		//增加sort属性才可以在GridView中显示排序链接
        $dataProvider->sort->attributes['author.name'] = [
            'asc' => ['au.name' => SORT_ASC],
            'desc' => ['au.name' => SORT_DESC],
        ];
        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }
        $createdFrom=($this->createdFrom!="")?strtotime($this->createdFrom):"";
        $createdTo=($this->createdTo!="")?strtotime($this->createdTo):"";
        $query->andFilterWhere(['like', 'title', $this->title])
            ->andFilterWhere(['like', 'content', $this->content]);
        $query->andFilterWhere(['>=', 'create_at', $createdFrom])
            ->andFilterWhere(['<=', 'create_at', $createdTo]);
        //别名au只能在sql语句中使用,在获取属性时还要使用全称author.name
		//在GridView的输入框中填写的关键字才会在author.name字段中进行搜索
        $query->andFilterWhere(['LIKE', 'au.name', $this->getAttribute('author.name')]);
        return $dataProvider;
    }
}

D:\phpwork\basic\models\Blog.php

<?php
namespace app\models;
use Yii;
/**
 * This is the model class for table "blog".
 *
 * @property string $id
 * @property string $title
 * @property string $content
 */
class Blog extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'blog';
    }
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['content'], 'string'],
            [['title'], 'string', 'max' => 50],
            [$this->attributes(),'safe'],
        ];
    }
    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'title' => Yii::t('app', 'Title'),
            'content' => Yii::t('app', 'Content'),
            'author.name'=>'作者',
        ];
    }
    /**
     * @inheritdoc
     * @return BlogQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new BlogQuery(get_called_class());
    }
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if($insert){
                $this->create_at=time();
            }
            $this->update_at=time();
            return true;
        } else {
            return false;
        }
    }

    public function getAuthor() {
        return $this->hasOne(Author::className(), ['id' => 'authorid']);
    }

}

D:\phpwork\basic\views\authorsql\multiple.php

<?php

use yii\helpers\Html;
use yii\grid\GridView;

/* @var $this yii\web\View */
/* @var $searchModel app\models\AuthorSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = Yii::t('app', 'Authors');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="author-index">
    <h1><?= Html::encode($this->title) ?></h1>
    <p>
        <?= Html::a(Yii::t('app', 'Create Author'), ['create'], ['class' => 'btn btn-success']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('Blog List', ['/blog/index'], ['class' => 'btn btn-default']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('AuthorInfo List', ['/authorsql/indexinfo'], ['class' => 'btn btn-default']) ?>
    </p>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'name',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
    <h1>Blog</h1>
    <?= GridView::widget([
        'dataProvider' => $blogProvider,
        'filterModel' => $blogModel,//将此行注释掉即可将GridView中的搜索框隐藏掉
        'columns' => [
            [
                'class' => 'yii\grid\SerialColumn',
            ],
            'title',
            'content',
            [
                'attribute' => 'create_at',
                'value' => function ($model,$key,$index, $column) {
                    //$model,当前的模型;$key,当前记录的键名;$index,当前记录的索引;$column,当前列的配置(是一个DataColumn对象)
                    return date("Y-n-j",$model->create_at);
                    //                    return date("Y-n-j",$model->create_at).',key:'.$key.',index:'.$index.',columnAttribute:'.$column->attribute;
                    //第3条记录的返回值:2017-3-24,key:3,index:2,columnAttribute:create_at
                },
            ],
            'author.name',//显示作者名称,而不是id
            [
                'class' => 'yii\grid\ActionColumn',
            ],
        ],
    ]); ?>
</div>
测试结果:
http://localhost:8081/authorsql/multiple
http://localhost:8081/authorsql/multiple?author-page=4&per-page=1&blog-page=2&blog-sort=content&author-sort=name
/*
Authors
Create Author      Blog List      AuthorInfo List
第3-3条,共5条数据.
#	Name	 
3	jingyong	  
« 1 2 3 4 5 »
Blog
第1-2条,共6条数据.
#	Title	Content	Create At	作者	 
1	PHP is Ok!	PHP is Ok! Content!	2017-3-24	Plark	  
2	My blog2	My blog Content2	2017-3-24	Johns	  
« 1 2 3 »
*/
在GridView中使用Pjax

Pjax小部件允许你更新一个页面中的特定部分,而不是重新加载整个页面,你可以使用它在过滤数据时仅更新GridView的内容部分。

use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin([
    // PJax options
]);
    Gridview::widget([
        // GridView options
    ]);
Pjax::end();

在Pjax小部件中为链接定义Pjax::$linkSelector ,则Pjax也可以正常运行。但对于ActionColumn中的链接来说会存在问题,要避免此种情况发生,可以通过编辑ActionColumn::$buttons 属性,在链接中添加HTML选项data-pjax="0"。

//默认情况下,Yii2已将操作按钮的data-pjax设置为0
<a href="/authorsql/1" title="查看" aria-label="查看" data-pjax="0"><span class="glyphicon glyphicon-eye-open"></span></a> 
<a href="/authorsql/update/1" title="更新" aria-label="更新" data-pjax="0"><span class="glyphicon glyphicon-pencil"></span></a> 
<a href="/authorsql/delete/1" title="删除" aria-label="删除" data-pjax="0" data-confirm="您确定要删除此项吗?" data-method="post"><span class="glyphicon glyphicon-trash"></span></a>

//第3页的链接代码:
<a href="/authorsql/pjax?page=3&amp;per-page=1&amp;sort=id&amp;_pjax=%23p0" data-page="2">3</a>
实例,Pjax在GridView中的应用

D:\phpwork\basic\controllers\AuthorsqlController.php

    public function actionPjax()
    {
        $searchModel = new AuthorSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->pagination->pageSize=1;
        return $this->render('pjax', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

D:\phpwork\basic\views\authorsql\pjax.php

<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
/* @var $this yii\web\View */
/* @var $searchModel app\models\AuthorSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('app', 'Authors-Pjax');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="author-index">
    <h1><?= Html::encode($this->title) ?></h1>
        <?= Html::a(Yii::t('app', 'Create Author'), ['create'], ['class' => 'btn btn-success']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('Blog List', ['/blog/index'], ['class' => 'btn btn-default']) ?>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <?= Html::a('AuthorInfo List', ['/authorsql/indexinfo'], ['class' => 'btn btn-default']) ?>
    </p>
	<!-- 链接点击后,此时间值如果变化了,则说明Pjax没有生效;否则Pjax正在起作用-->
    <?=time()?>
    <?
    Pjax::begin([
//        'linkSelector'=>false,//false,将Pjax中的链接取消Pjax点击效果,仅对链接有效,对于搜索筛选框无效。
        'linkSelector'=>null,//null,默认值,Pjax中的所有链接自动触发Pjax点击效果,仅对局部页面做更新操作。
    ]);
	//需要echo才能显示出来内容
    echo GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'id',
            'name',
            [
                'class' => 'yii\grid\ActionColumn',
                'contentOptions' => ['class' => 'text-center'],//将操作链接按钮居中
            ],
        ],
    ]);
    Pjax::end();
    ?>
</div>

<? //在Gii中GridView/ListView中使用Pjax(GridView/ListView with Pjax in Gii) 自2.0.5版本起,Gii的CRUD生成器有一个选项叫作$enablePjax ,此选项可以在web页面或命令行中使用。

yii gii/crud --controllerClass="backend\\controllers\PostController" \
  --modelClass="common\\models\\Post" \
  --enablePjax=1

将生成一个Pjax小部件,它将GridView或ListView小部件包裹在其中。

4、Further reading(深入阅读)

Arno Slatius所著的Rendering Data in Yii 2 with GridView: https://www.sitepoint.com/rendering-data-in-yii-2-with-gridview-and-listview/

(全文完)

觉得很赞
    没有找到数据。
您需要登录后才可以回复。登录 | 立即注册