最近剛開始用yii2,真是超棒的,但是也有許多不足的地方,今天要說的就是GridView鏈接問題。
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'username',
'email',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
這是一個最簡單的默認 GridView,gii生成的就這樣,那么問題來了。
如果用戶管理不是獨立的控制器,而是在user控制器或者是site控制器下,ActionColumn默認鏈接卻是view, update, delete
但是我想要的卻是 user-view, user-update, user-delete 這樣的鏈接,然后我修改了下,代碼如下。
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'username',
'email',
[
'class' => 'yii\grid\ActionColumn',
'template' => '{user-view} {user-update} {user-delete}',
],
],
]); ?>
結果,什么都沒了,為什么呢?然后我打開 yii\grid\ActionColumn,看了源碼,發現他默認只渲染了view, update, delete
如果 {user-view} 這樣的標簽在按鈕組(buttons[])里不存在,就輸出空。

所以我們還要添加按鈕才行,然后代碼就成了這樣。
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'username',
'email',
[
'class' => 'yii\grid\ActionColumn',
'template' => '{user-view} {user-update} {user-delete}',
'buttons' = [
// 下面代碼來自於 yii\grid\ActionColumn 簡單修改了下
'user-view' => function ($url, $model, $key) {
$options = [
'title' => Yii::t('yii', 'View'),
'aria-label' => Yii::t('yii', 'View'),
'data-pjax' => '0',
];
return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, $options);
},
'user-update' => function ($url, $model, $key) {
$options = [
'title' => Yii::t('yii', 'Update'),
'aria-label' => Yii::t('yii', 'Update'),
'data-pjax' => '0',
];
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
},
'user-delete' => function ($url, $model, $key) {
$options = [
'title' => Yii::t('yii', 'Delete'),
'aria-label' => Yii::t('yii', 'Delete'),
'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
'data-method' => 'post',
'data-pjax' => '0',
];
return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, $options);
},
]
],
],
]); ?>
這樣就OK了,但是代碼變的超惡心,這不是我想要的,於是我重寫了 yii\grid\ActionColumn 增強了 template 的功能。
類似 'template' => '{url-link:type}' 這樣的,這里的 url-link 就是你的鏈接地址,type就是按鈕類型,默認的3類按鈕還在。
例如:'template' => '{user-view:view} {user-update:update} {user-del:delete}'
這樣地址和樣式都可以簡單搞定,當然你依然可以自定義按鈕,方法跟上面那個一樣。
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'username',
'email',
[
'class' => 'backend\components\ActionColumn',
'template' => '{user-view:view} {user-update:update} {user-del:delete} {user-diy-btn:diy}',
'buttons' => [
// 自定義按鈕
'diy' => function ($url, $model, $key) {
$options = [
'title' => Yii::t('yii', 'View'),
'aria-label' => Yii::t('yii', 'View'),
'data-pjax' => '0',
];
return Html::a('<span class="glyphicon glyphicon-refresh"></span>', $url, $options);
},
]
],
],
]); ?>
你只要增加一個 diy 類型的按鈕就OK了,如果常用的話,你完全可以直接寫到 backend\components\ActionColumn 這里面。
效果如下。

這才是理想的狀態,好了,下面給出這個 ActionColumn 代碼吧。
我是放在 backend\components 目錄下,你也可以放在其他你自己喜歡的地方,命名空間改下就OK了。
namespace backend\components;
class ActionColumn extends \yii\grid\ActionColumn
{
public $template = '{:view} {:update} {:delete}';
/**
* 重寫了標簽渲染方法。
* @param mixed $model
* @param mixed $key
* @param int $index
* @return mixed
*/
protected function renderDataCellContent($model, $key, $index)
{
return preg_replace_callback('/\\{([^}]+)\\}/', function ($matches) use ($model, $key, $index) {
list($name, $type) = explode(':', $matches[1].':'); // 得到按鈕名和類型
if (!isset($this->buttons[$type])) { // 如果類型不存在 默認為view
$type = 'view';
}
if ('' == $name) { // 名稱為空,就用類型為名稱
$name = $type;
}
$url = $this->createUrl($name, $model, $key, $index);
return call_user_func($this->buttons[$type], $url, $model, $key);
}, $this->template);
}
}
<input type="button" class="btn btn-success" value="點擊投票" >
class="am-btn am-btn-secondary am-btn-xs" class="am-icon-search"查看
class="am-btn am-btn-warning am-btn-xs" class="am-icon-edit"修改
btn-warning 黃色 success 綠色
plus 顯示加號 ok 顯示對號 remove 顯示錯號 eye-open 顯示眼符號
open 顯示上傳 pencil 顯示鉛筆 trash 顯示刪除 refresh 顯示刷新
分頁顯示:
'pagination' =>[
'pagesize' => '3',
]
'pager' => ['activePageCssClass'=>'active','options'=>['class'=>'pagination pagination-default'],],


想在某列td上應用樣式。
老寫法是這樣的
<?= GridView::widget([
'dataProvider' => $dataProvider, 'layout' => "{items}\n{pager}\n{summary}", 'summary' => '<p class="summary">當前顯示第{begin} - {end}條,共{totalCount}條。</p>', 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'name', [ // 看這里 'attribute' => 'propertyValuesString', 'format' => 'html', 'value' => function ($model, $key, $index, $column){ return '<div class="limit-width">'. $model->propertyValuesString .'</div>'; } ], ......
這樣返回的html,td標簽里面會套一層<div class="limit-width"></div>。
如果才能將class應用在td上呢
查了源碼之后,可以這樣:
<?= GridView::widget([
.......
'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'name',
// 新增的代碼
[
'class' => 'yii\grid\Column',
'contentOptions' => [ 'class' => 'limit-width', ], 'header' => '類目下的所有種類', 'content' => function ($model, $key, $index, $column){ return $model->propertyValuesString; } ],
也就是說。該列我需要用到 yii/grid/Column類。該類有個contentOptions屬性。接收匿名函數或數組。數組就是屬性名和屬性值得鍵值對。渲染時該列包含一個th和多個td。th內容從header中取,td就是content。
'rowOptions' => function($model, $key, $index, $grid) { return ['class' => $model->isEnabled ? 'label-green' : 'label-red']; }
要添加復選框列到[[yii\grid\GridView]],如下添加它到[[yii\grid\GridView::$columns|columns]]配置:
echo
GridView::widget([
'dataProvider'
=>
$dataProvider
,
'columns'
=> [
// ...
[
'class'
=>
'yii\grid\CheckboxColumn'
,
// 在此配置其他屬性
],
],
用戶可以點擊復選框來選擇網格的行。被選中的行可調用以下 JavaScript 代碼獲取:
var
keys = $(
'#grid'
).yiiGridView(
'getSelectedRows'
);
// keys 是鍵名關聯到選中行的數組
數據篩選
要篩選數據,表格視圖需要一個模型從過濾的表單取得輸入數據,並調整 dataprovider 的查詢語句到期望的搜索條件。使用active records的慣例是建立一個搜索模型類繼承活動記錄類。然后用這個類定義搜索的驗證規則和提供 search() 方法來返回 data provider 。
要給 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()
{
// bypass 父類實現的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
->name])
->andFilterWhere([
'like'
,
'creation_date'
,
$this
->creation_date]);
return
$dataProvider
;
}
}
你可以在控制器使用這個方法來為表格視圖獲取 dataProvider :
$searchModel
=
new
PostSearch();
$dataProvider
=
$searchModel
->search(
$_GET
);
return
$this
->render(
'myview'
, [
'dataProvider'
=>
$dataProvider
,
'searchModel'
=>
$searchModel
,
]);
然后在視圖將 $dataProvider 和 $searchModel 賦值給表格視圖:
echo
GridView::widget([
'dataProvider'
=>
$dataProvider
,
'filterModel'
=>
$searchModel
,
]);
使用模型關系
當使用 GridView 顯示活動記錄(active records)時,你可能會遇到需要顯示關聯模型列的數值,比如想顯示文章的作者的名字而不是他的 id。你可以在 columns 里面把這個屬性名定義為 author.name ,當 Post 模型存在一個名為 author 的關系並且這個 author 模型擁有一個 name 屬性,GridView將能顯示作者的名字,不過缺省情況下,排序和過濾沒有被啟用。你得調整 PostSearch 模型(在最后部分介紹過)來添加這個功能。
為了啟用關聯列的排序,你得聯合(join)這個關聯表,並添加排序規則到數據提供器(data provider)的 Sort 組件中:
$query
= Post::find();
$dataProvider
=
new
ActiveDataProvider([
'query'
=>
$query
,
]);
// 連接關聯 `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')]);添加另一個過濾條件。

