# 數據小部件
Yii提供了一套數據小部件?[widgets](http://www.yiichina.com/doc/guide/2.0/structure-widgets)?,這些小部件可以用于顯示數據。?[DetailView](http://www.yiichina.com/doc/guide/2.0/output-data-widgets#detail-view)?小部件能夠用于顯示一條記錄數據,?[ListView](http://www.yiichina.com/doc/guide/2.0/output-data-widgets#list-view)?和[GridView](http://www.yiichina.com/doc/guide/2.0/output-data-widgets#grid-view)?小部件能夠用于顯示一個擁有分頁、排序和過濾功能的一個列表或者表格。
## DetailView
yii\widgets\DetailView 小部件顯示的是單一 yii\widgets\DetailView::$model 數據的詳情。
它非常適合用常規格式顯示一個模型(例如在一個表格的一行中顯示模型的每個屬性)。 這里說的模型可以是 \yii\base\Model 或者其子類的一個實例,例如子類?[active record](http://www.yiichina.com/doc/guide/2.0/db-active-record),也可以是一個關聯數組。
DetailView使用 yii\widgets\DetailView::$attributes 屬性來決定顯示模型哪些屬性以及如何格式化。 可用的格式化選項,見?[formatter section](http://www.yiichina.com/doc/guide/2.0/output-formatting)?章節。
一個典型的DetailView的使用方法如下:
~~~
echo DetailView::widget([
'model' => $model,
'attributes' => [
'title', // title attribute (in plain text)
'description:html', // description attribute formatted as HTML
[ // the owner name of the model
'label' => 'Owner',
'value' => $model->owner->name,
],
'created_at:datetime', // creation date formatted as datetime
],
]);
~~~
## ListView
yii\widgets\ListView 小部件用于顯示數據提供者?[data provider](http://www.yiichina.com/doc/guide/2.0/output-data-providers)?提供的數據。 每個數據模型用指定的視圖文件 yii\widgets\ListView::$itemView 來渲染。 因為它提供開箱即用式的(譯者注:封裝好的)分頁、排序以及過濾這樣一些特性,所以它可以很方便地為最終用戶顯示信息并同時創建數據管理界面。
一個典型的用法如下例所示:
~~~
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
$dataProvider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
]);
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
]);
~~~
`_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,是小部件的實例。
假如你需要傳遞附加數據到每一個視圖中,你可以像下面這樣用 yii\widgets\ListView::$viewParams 屬性傳遞鍵值對:
~~~
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
'viewParams' => [
'fullView' => true,
'context' => 'main-page',
// ...
],
]);
~~~
在視圖中,上述這些附加數據也是可以作為變量來使用的。
## GridView
數據網格或者說 GridView 小部件是Yii中最強大的部件之一。如果你需要快速建立系統的管理后臺, GridView 非常有用。它從數據提供者?[data provider](http://www.yiichina.com/doc/guide/2.0/output-data-providers)?中取得數據并使用 yii\grid\GridView::columns 屬性的一組列配置,在一個表格中渲染每一行數據。
表中的每一行代表一個數據項的數據,并且一列通常表示該項的屬性(某些列可以對應于屬性或靜態文本的復雜表達式)。
使用GridView的最少代碼如下:
~~~
use yii\grid\GridView;
use yii\data\ActiveDataProvider;
$dataProvider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
]);
~~~
上面的代碼首先創建了一個數據提供者,然后使用GridView顯示每一行的每個屬性,每一行的數據是從數據提供者取來的。 展現出來的表格封裝了排序以及分頁功能。
### 表格列
表格的列是通過 yii\grid\Column 類來配置的,這個類是通過 GridView 配置項中的 yii\grid\GridView::columns 屬性配置的。根據列的類別和設置的不同,各列能夠以不同方式展示數據。 默認的列類是 yii\grid\DataColumn,用于展現模型的某個屬性, 并且可以排序和過濾。
~~~
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// 數據提供者中所含數據所定義的簡單的列
// 使用的是模型的列的數據
'id',
'username',
// 更復雜的列數據
[
'class' => 'yii\grid\DataColumn', //由于是默認類型,可以省略
'value' => function ($data) {
return $data->name; // 如果是數組數據則為 $data['name'] ,例如,使用 SqlDataProvider 的情形。
},
],
],
]);
~~~
請注意,假如配置中沒有指定 yii\grid\GridView::columns 屬性,那么Yii會試圖顯示數據提供者的模型中所有可能的列。
### 列類
通過使用不同類,網格列可以自定義:
~~~
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\SerialColumn', // <-- 這里
// 你還可以在此配置其他屬性
],
~~~
除了我們下面將要展開討論的Yii自帶的列類,你還可以創建你自己的列類。
每個列類是從 yii\grid\Column 擴展而來, 從而在配置網格列的時候,你可以設置一些公共的選項。
* yii\grid\Column::header 允許為頭部行設置內容。
* yii\grid\Column::footer 允許為尾部行設置內容。
* yii\grid\Column::visible 定義某個列是否可見
* yii\grid\Column::content 允許你傳遞一個有效的PHP回調來為一行返回數據,格式如下:
~~~
function ($model, $key, $index, $column) {
return 'a string';
}
~~~
你可以傳遞數組來指定各種容器式的HTML選項:
* yii\grid\Column::headerOptions
* yii\grid\Column::footerOptions
* yii\grid\Column::filterOptions
* yii\grid\Column::contentOptions
#### 數據列
yii\grid\DataColumn 用于顯示和排序數據。這是默認的列的類型, 所以在使用 DataColumn 為列類時,可省略類的指定(譯者注:不需要'class'選項的意思)。
數據列的主要配置項是 yii\grid\DataColumn::format 屬性。它的值對應于?`formatter`?[application component](http://www.yiichina.com/doc/guide/2.0/structure-application-components)?應用組件里面的一些方法, 默認是使用 \yii\i18n\Formatter 應用組件:
~~~
echo GridView::widget([
'columns' => [
[
'attribute' => 'name',
'format' => 'text'
],
[
'attribute' => 'birthday',
'format' => ['date', 'php:Y-m-d']
],
],
]);
~~~
在上面的代碼中,`text`?對應于 \yii\i18n\Formatter::asText()。列的值作為第一個參數傳遞。在第二列的定義中,`date`?對應于 \yii\i18n\Formatter::asDate()。 同樣地,列值也是通過第一個參數傳遞的,而 'php:Y-m-d' 用作第二個參數的值。
可用的格式化方法列表,請參照?[section about Data Formatting](http://www.yiichina.com/doc/guide/2.0/output-formatting)。
數據列配置,還有一個”快捷格式化串”的方法,詳情見API文檔 yii\grid\GridView::columns。 (譯者注:舉例說明,`"name:text:Name"`?快捷格式化串,表示列名為?`name`?格式為?`text`?顯示標簽是?`Name`)
#### 動作列
yii\grid\ActionColumn 用于顯示一些動作按鈕,如每一行的更新、刪除操作。
~~~
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\ActionColumn',
// you may configure additional properties here
],
~~~
可配置的屬性如下:
* yii\grid\ActionColumn::controller 是應該執行這些動作的控制器ID。 如果沒有設置,它將使用當前控制器。
* yii\grid\ActionColumn::template 定義在動作列中使用的構建每個單元格的模板。 在大括號內括起來的的令牌被當做是控制器的 action 方法ID (在動作列的上下文中也稱作*按鈕名稱*)。 它們將會被 yii\grid\ActionColumn::$buttons 中指定的對應按鈕的關聯的渲染回調函數替代。 例如,令牌?`{view}`?將被?`buttons['view']`?關聯的渲染回調函數的返回結果所替換。 如果沒有找到回調函數,令牌將被替換成一個空串。默認的令牌有?`{view} {update} {delete}`?。
* yii\grid\ActionColumn::buttons 是一個按鈕的渲染回調數數組。數組中的鍵是按鈕的名字(沒有花括號),并且值是對應的按鈕渲染回調函數。 這些回調函數須使用下面這種原型:
~~~
function ($url, $model, $key) {
// return the button HTML code
}
~~~
在上面的代碼中,`$url`?是列為按鈕創建的URL,`$model`是當前要渲染的模型對象,并且?`$key`?是在數據提供者數組中模型的鍵。
* yii\grid\ActionColumn::urlCreator 是使用指定的模型信息來創建一個按鈕URL的回調函數。 該回調的原型和 yii\grid\ActionColumn::createUrl() 是一樣的。 假如這個屬性沒有設置,按鈕的URL將使用 yii\grid\ActionColumn::createUrl() 來創建。
#### 復選框列
yii\grid\CheckboxColumn 顯示一個復選框列。
想要添加一個復選框到網格視圖中,將它添加到 yii\grid\GridView::$columns 的配置中,如下所示:
~~~
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
// ...
[
'class' => 'yii\grid\CheckboxColumn',
// 你可以在這配置更多的屬性
],
],
~~~
用戶可點擊復選框來選擇網格中的一些行。被選擇的行可通過調用下面的JavaScript代碼來獲得:
~~~
var keys = $('#grid').yiiGridView('getSelectedRows');
// keys 為一個由與被選行相關聯的鍵組成的數組
~~~
#### 序號列
yii\grid\SerialColumn 渲染行號,以?`1`?起始并自動增長。
使用方法和下面的例子一樣簡單:
~~~
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'], // <-- here
// ...
~~~
### 數據排序
> 注意:這部分正在開發中。
>
> * [https://github.com/yiisoft/yii2/issues/1576](https://github.com/yiisoft/yii2/issues/1576)
### 數據過濾
為了過濾數據的 GridView 需要一個模型?[model](http://www.yiichina.com/doc/guide/2.0/structure-models)?來 從過濾表單接收數據,以及調整數據提供者的查詢對象,以滿足搜索條件。 使用活動記錄?[active records](http://www.yiichina.com/doc/guide/2.0/db-active-record)?時,通常的做法是 創建一個能夠提供所需功能的搜索模型類(可以使用?[Gii](http://www.yiichina.com/doc/guide/2.0/start-gii)?來生成)。 這個類為搜索定義了驗證規則并且提供了一個將會返回數據提供者對象的?`search()`?方法。
為了給?`Post`?模型增加搜索能力,我們可以像下面的例子一樣創建?`PostSearch`?模型:
~~~
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class PostSearch extends Post
{
public function rules()
{
// 只有在 rules() 函數中聲明的字段才可以搜索
return [
[['id'], 'integer'],
[['title', 'creation_date'], 'safe'],
];
}
public function scenarios()
{
// 旁路在父類中實現的 scenarios() 函數
return Model::scenarios();
}
public function search($params)
{
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// 從參數的數據中加載過濾條件,并驗證
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
// 增加過濾條件來調整查詢對象
$query->andFilterWhere(['id' => $this->id]);
$query->andFilterWhere(['like', 'title', $this->title])
->andFilterWhere(['like', 'creation_date', $this->creation_date]);
return $dataProvider;
}
}
~~~
你可以在控制器中使用如下方法為網格視圖獲取數據提供者:
~~~
$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' => [
// ...
],
]);
~~~
### 處理關系型模型
當我們在一個網格視圖中顯示活動數據的時候,你可能會遇到這種情況,就是顯示關聯表的列的值,例如:發帖者的名字,而不是顯示他的?`id`。 當?`Post`?模型有一個關聯的屬性名(譯者注:?`Post`?模型中用?`hasOne`?定義?`getAuthor()`?函數) 叫?`author`?并且作者模型(譯者注:本例的作者模型是?`users`?)有一個屬性叫?`name`,那么你可以通過在 yii\grid\GridView::$columns 中定義屬性名為`author.name`?來處理。這時的網格視圖能顯示作者名了,但是默認是不支持按作者名排序和過濾的。 你需要調整上個章節介紹的`PostSearch`?模型,以添加此功能。
為了使關聯列能夠排序,你需要連接關系表,以及添加排序規則到數據提供者的排序組件中:
~~~
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// 連接與 `users` 表相關聯的 `author` 表
// 并將 `users` 表的別名設為 `author`
$query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
// 使得關聯字段可以排序
$dataProvider->sort->attributes['author.name'] = [
'asc' => ['author.name' => SORT_ASC],
'desc' => ['author.name' => SORT_DESC],
];
// ...
~~~
過濾也需要像上面一樣調用joinWith方法。你也需要在屬性和規則中定義該列,就像下面這樣:
~~~
public function 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()`?等地方使用關聯名稱。
>
> 例如,你使用?`au`?作為作者關系表的別名,那么聯查語句就要寫成像下面這樣:
>
> ~~~
> $query->joinWith(['author' => function($query) { $query->from(['au' => 'users']); }]);
> ~~~
>
> 當別名已經在關聯函數中定義了時,也可以只調用?`$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],
> ];
> ~~~
>
> 同樣,當指定使用 yii\data\Sort::defaultOrder 來排序的時候,你需要使用關聯名稱替代別名:
>
> ~~~
> $dataProvider->sort->defaultOrder = ['author.name' => SORT_ASC];
> ~~~
> 信息:更多關于?`joinWith`?和在后臺執行查詢的相關信息, 可以查看?[active record docs on joining with relations](http://www.yiichina.com/doc/guide/2.0/db-active-record#joining-with-relations)。
#### SQL視圖用于過濾、排序和顯示數據
還有另外一種方法可以更快、更有用 - SQL 視圖。例如,我們要在?`GridView`?中顯示用戶和他們的簡介,可以這樣創建 SQL 視圖:
~~~
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
~~~
然后你需要創建活動記錄模型來代表這個視圖:
~~~
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 [
// 在這定義你的規則
];
}
/**
* @inheritdoc
*/
public static function attributeLabels()
{
return [
// 在這定義你的屬性標簽
];
}
}
~~~
之后你可以使用這個 UserView 活動記錄和搜索模型,無需附加的排序和過濾屬性的規則。 所有屬性都可開箱即用。請注意,這種方法有利有弊:
* 你不需要指定不同排序和過濾條件,一切都包裝好了;
* 它可以更快,因為數據的大小,SQL查詢的執行(對于每個關聯數據你都不需要額外的查詢)都得到優化;
* 因為在SQL視圖中這僅僅是一個簡單的映射UI,所以在你的實體中,它可能缺乏某方面的邏輯,所以,假如你有一些諸如`isActive`、`isDeleted`?或者其他影響到UI的方法, 你也需要在這個類中復制他們。
### 單個頁面多個網格視圖部件
你可以在一個單獨頁面中使用多個網格視圖,但是一些額外的配置是必須的,為的就是它們相互之間不干擾。 當使用多個網格視圖實例的時候,你必須要為生成的排序和分頁對象配置不同的參數名,以便于每個網格視圖有它們各自獨立的排序和分頁。 你可以通過設置 yii\data\Sort::sortParam 和 yii\data\Pagination::pageParam,對應于數據提供者的 yii\data\BaseDataProvider::$sort 和 yii\data\BaseDataProvider::$pagination 實例。
假如我們想要同時顯示?`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,
]);
~~~
### Using GridView with Pjax
> 注意: 這部分正在開發中。
待定
- 介紹(Introduction)
- 關于 Yii(About Yii)
- 從 Yii 1.1 升級(Upgrading from Version 1.1)
- 入門(Getting Started)
- 安裝 Yii(Installing Yii)
- 運行應用(Running Applications)
- 第一次問候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩轉 Databases(Working with Databases)
- 用 Gii 生成代碼(Generating Code with Gii)
- 更上一層樓(Looking Ahead)
- 應用結構(Application Structure)
- 結構概述(Overview)
- 入口腳本(Entry Scripts)
- 應用(Applications)
- 應用組件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 視圖(Views)
- 模塊(Modules)
- 過濾器(Filters)
- 小部件(Widgets)
- 前端資源(Assets)
- 擴展(Extensions)
- 請求處理(Handling Requests)
- 運行概述(Overview)
- 引導(Bootstrapping)
- 路由引導與創建 URL(Routing and URL Creation)
- 請求(Requests)
- 響應(Responses)
- Sessions and Cookies
- 錯誤處理(Handling Errors)
- 日志(Logging)
- 關鍵概念(Key Concepts)
- 組件(Components)
- 屬性(Properties)
- 事件(Events)
- 行為(Behaviors)
- 配置(Configurations)
- 別名(Aliases)
- 類自動加載(Class Autoloading)
- 服務定位器(Service Locator)
- 依賴注入容器(Dependency Injection Container)
- 配合數據庫工作(Working with Databases)
- 數據庫訪問(Data Access Objects): 數據庫連接、基本查詢、事務和模式操作
- 查詢生成器(Query Builder): 使用簡單抽象層查詢數據庫
- 活動記錄(Active Record): 活動記錄對象關系映射(ORM),檢索和操作記錄、定義關聯關系
- 數據庫遷移(Migrations): 在團體開發中對你的數據庫使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用戶數據(Getting Data from Users)
- 創建表單(Creating Forms)
- 輸入驗證(Validating Input)
- 文件上傳(Uploading Files)
- 收集列表輸入(Collecting Tabular Input)
- 多模型同時輸入(Getting Data for Multiple Models)
- 顯示數據(Displaying Data)
- 格式化輸出數據(Data Formatting)
- 分頁(Pagination)
- 排序(Sorting)
- 數據提供器(Data Providers)
- 數據小部件(Data Widgets)
- 操作客戶端腳本(Working with Client Scripts)
- 主題(Theming)
- 安全(Security)
- 認證(Authentication)
- 授權(Authorization)
- 處理密碼(Working with Passwords)
- 客戶端認證(Auth Clients)
- 安全領域的最佳實踐(Best Practices)
- 緩存(Caching)
- 概述(Overview)
- 數據緩存(Data Caching)
- 片段緩存(Fragment Caching)
- 分頁緩存(Page Caching)
- HTTP 緩存(HTTP Caching)
- RESTful Web 服務
- 快速入門(Quick Start)
- 資源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化響應(Response Formatting)
- 授權驗證(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 錯誤處理(Error Handling)
- 開發工具(Development Tools)
- 調試工具欄和調試器(Debug Toolbar and Debugger)
- 使用 Gii 生成代碼(Generating Code using Gii)
- TBD 生成 API 文檔(Generating API Documentation)
- 測試(Testing)
- 概述(Overview)
- 搭建測試環境(Testing environment setup)
- 單元測試(Unit Tests)
- 功能測試(Functional Tests)
- 驗收測試(Acceptance Tests)
- 測試夾具(Fixtures)
- 高級專題(Special Topics)
- 高級應用模版(Advanced Project Template)
- 從頭構建自定義模版(Building Application from Scratch)
- 控制臺命令(Console Commands)
- 核心驗證器(Core Validators)
- 國際化(Internationalization)
- 收發郵件(Mailing)
- 性能優化(Performance Tuning)
- 共享主機環境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代碼(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手類(Helpers)
- 助手一覽(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)