【YII2】使用GridView和ListView展现数据

当你想将数据库表中的数据进行展现时,yii提供了DataProviders,它含有若干组件来输出数据。在这其中,ListView 和 GridView具了强大的功能。html


建立示例数据库sql


下面是一个博客系统的部分表,表之间存在关联数据库

图片

从上面的数据表设计,在yii的models中应该含有以下关系:数组

1. Authors model中含有getArticles()方法,用于关联Articles模型(一对多);app

2. Articles model中含有getAuthor()方法关联Author(多对一),getTags()方法关联Tags(多对多);yii

3. Tags model中含有getArticles()关联Articles(多对多)。ide


DataProviders函数


关于DataProviders,有三种不一样的类型:this

【ActiveDataProvider】为ActiveQuery的示例,一般会将models变为数组。在通常的ActiveQuery模型下,一般用它进行保存渲染,创建数据关联。spa

【ArrayDataProvider】 结果集为数组,在建立自定义样式下,此类型很是实用。

【SqlDataProvider】 经过sql得到的结果集,更加原生。


除了在views下展现不一样外,以上三种没有太大区别。数据提供自己是一个基础组件,能够对数据进行展现,对数据分页,排序等。


ActiveDataProvider


ActiveQuery的实例,全部model::find()都将返回ActiveDataProvider模型,建立很是容易:


/* 全部文章数据的dataProvider */

$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('tags'),

]);


/* 使用到了做者与文章的关联,返回一我的的全部文章 */

$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('author')->where(['Name'=>'Arno Slatius']),

]);


$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('author')->where(['Name'=>'Arno Slatius'])->orderBy('Published'),

]);


最后一个例子须要特殊注意,这里限制了DataProvider的排序,一会将会再次说明排序的问题。


SqlDataProvider


这个模型是经过执行sql语句获取的,下面是一个例子:


$dataProvider = new SqlDataProvider([

    'sql' => 'SELECT Name, Title, COUNT(ArticleTags.ID) AS TagCount ' . 

             'FROM Authors ' .

             'INNER JOIN Articles ON (Authors.ID = Articles.AuthorID) ' .

             'INNER JOIN ArticleTags ON (Articles.ID = ArticleTags.ID) ' .

             'WHERE Name=:author' .

             'GROUP BY ArticleID',

    'params' => [':author' => 'Arno Slatius'],

]);


使用sql查询获取数据是一个不错的选择,使用ActiveRecord链接数据库是很是好的办法,但对大型数据库制定一些标准时会变得很复杂,

若是你很擅长sql语句,你会用到大量的joins,unions,而且聚合你想要的数据经过建立sql查询的方法,来构建你的DataProvider。


ArrayDataProvider


示例:

$dataProvider = new ArrayDataProvider([

    'allModels' => Authors::find()->all(),

]);


上面会以数据返回全部的做者。

下面我想获取全部人的文章数量和最后发表时间,须要继承ArrayDataProvider。init()方法在类建立时调用。

namespace app\data;


use \app\models\Authors;

use \app\models\Articles;


class AuthorsReportProvider extends \yii\data\ArrayDataProvider

{

/**

     * Initialize the dataprovider by filling allModels

     */

    public function init()

    {

        //Get all all authors with their articles

    $query = Authors::find()->with('articles');

foreach($query->all() as $author) {

//Get the last published date if there are articles for the author

if (count($author->articles)) {

$lastPublished = $query->max('Published');

} else {

$lastPublished = null;

}


//Add rows with the Author, # of articles and last publishing date

$this->allModels[] = [

'name' => $authors->Name,

'articles' => count($author->articles),

'last' => $lastPublished,

];

}

}

}


$this->allModels返回我想要的数据。


数据可视化


有两种方式能够对数据进行展现:

GridView:

在HTML的表格(table)中展现,配置好以后,将会自动添加表头,点击排序,分页,展现数字总和等。

ListView:

容许自定义局部展现,很是经常使用的有时候使用<li>标签进行数据展现。


来看下面的实例:

/* A dataprovider with all articles */

$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('tags','authors'),

]);


with()方法可让Articles直接与tags、authors进行关联,获取想要的数据。


下面使用GridView渲染试图,只展现了几个字段:

<?= GridView::widget([

    'dataProvider' => $dataProvider,

    'columns' => [

        'ID',

        'Author',

        'Title',

        'Published:date',

    ],

]); ?>


界面展现以下:

图片

I do admit that I cheated slightly by defining a page size of 6 and three columns by which it can sort; more on that later. Note the summary at the top, the sort links in the column headers and the pager at the bottom. Everything is formatted in a localized format (Dutch for me) where applicable. I needed no additional code to get the handling of links for the sorting or next pages working. The links are all automatically generated by the widget and actions are handled by the DataProvider. This component makes life really easy out of the box.(妈蛋不想翻译了)


列表中会用到其余表的数据,最简单的方法直接 代表.字段名 便可,格式化数据时可使用匿名函数。

<?= GridView::widget([

'dataProvider' => $dataProvider,

        'columns' => [

        'Title',

        'author.Name',

        [

            'attribute' => 'author.Twitter',

            'type' => 'html',

            'value' => function($model) {

            return Html::link('@' . $model->author->Twitter, 'http://twitter.com/' . $model->author->Twitter);

            }

        ],

        [

        'attribute' => 'tags',

        'value' => function($model) {

        return implode(', ', ArrayHelper::map($model->tags, 'ID', 'Tag'));

    }

],

'Published:date',

],

]); ?>



上面columns每一列都继承了yii\grid\Column,因此可使用它的全部属性和方法。

例如yii\grid\DataColumn有一个$footer属性,因此这里能够展现一行显示底部信息,固然别忘了设置showFooter为true


GridView还有不少其余属性能够配置使用,下面例子中使用了部分:


<?= GridView::widget([

'dataProvider' => $dataProvider,

        'columns' => [

        ...

        ],

        'layout' => '{summary}{items}{pager}',

'filterPosition' => FILTER_POS_FOOTER,

'rowOptions' => function ($model, $key, $index, $grid) {

},

'emptyText' => '-',

'showFooter' => true,

    ]); ?>



layout属性很是有用,它能够改变基本元素的展现,能够增长{summary}, {errors}, {items}, {sorter}, {pager} 等元素,

在你的页面中颇有可能须要展现这些信息。

filterPosition能够把过滤器移动到底部,或者内容中间。不设置的话默认在头部引入。


个性化排序和分页


GridView默认会有排序和分页,它配置在yii\data\BaseDataProvider中。能够修改初始化参数改变其展现内容。

好比pageSize,默认展现每页20条,能够改变它来配置


/* show 80 items per page */

$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('tags'),

    'pagination' => [

    'pagesize' => 80,

    ],

]);


/* disable pagination, shows all items at once */

...

    'pagination' => false,

...

    'pagination' => [

    'pagesize' => -1,    //Alternate method of disabling paging

    ],

...


一样有一些参数来配置排序的展现,首先,你能够自定义排序,You can supply multiple attributes to sort on for each column. When you use the GridView you might find that the default sort handling sometimes fails on more complex attributes or on values that you output using unnamed functions. In these situations, supplying sort attributes also helps.


以下示例代码:

$dataProvider = new ActiveDataProvider([

    'query' => Articles::find()->with('authors'),

    'sort' => [

    'defaultOrder' => [

        'Published' => SORT_DESC,

        'LastEdited' => SORT_DESC,

    ],

    'attributes' => [

    'name' => [

                'asc' => [

                    'author.Name' => SORT_ASC, 

                    'Published' => SORT_ASC,

                    'Title' => SORT_ASC,

                ],

                'desc' => [

                    'author.Name' => SORT_DESC

                    'Published' => SORT_DESC,

                    'Title' => SORT_DESC,

                ],

            ],

            ... etc ...

    ],

    ],

]);


The defaultOrder changed, as you might guess, the initial ordering of the GridView, should it be rendered. In this example the ordering will be on ‘Published’ decending and ‘LastEdited’ descending next.


attributes will contain a list of all sortable attributes from the GridView’s columns (the attribute names here should match the attribute names in the GridView). You can independently define how the ascending and descending result will be sorted – again, this can be done on multiple columns in your DB.


One thing to note that for pagination to work the DataProvider needs to know the total number of results available. The  ActiveDataProvider and SqlDataProvider are able to do it by default using database queries. If you use the ArrayDataProvider, you might need to do some additional work depending on how you fill the provider.


结论


ListView 和 GridView是让你展现数据很是实用的组件。若是你想进一步了解,请点击 ‘GridView on steroids’ 由另外一个老外所写,他里面增长了更多的功能。

相关文章
相关标签/搜索