當你想將數據庫表中的數據進行展現時,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’ 由另外一個老外所寫,他裏面增長了更多的功能。