Yii 提供了一组 小部件,可用于显示数据。虽然 DetailView 小部件可以用于显示单个记录的数据,但 ListView 和 GridView 可以用于显示数据记录的列表或表格,提供分页、排序和过滤等功能。
DetailView 小部件显示单个数据 模型 的详细信息。
它最适合用于以常规格式显示模型(例如,每个模型属性都作为表格中的一行显示)。模型可以是 yii\base\Model 的实例或子类,例如 活动记录 或关联数组。
DetailView 使用 $attributes 属性来确定要显示哪些模型属性以及如何对其进行格式化。有关可用的格式化选项,请参见 格式化程序部分。
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,
'contentOptions' => ['class' => 'bg-red'], // HTML attributes to customize value tag
'captionOptions' => ['tooltip' => 'Tooltip'], // HTML attributes to customize label tag
],
'created_at:datetime', // creation date formatted as datetime
],
]);
请记住,与 yii\widgets\GridView 处理一组模型不同,DetailView 只处理一个模型。因此,大多数情况下不需要使用闭包,因为 $model
是唯一用于显示的模型,并且在视图中作为一个变量可用。
但是,在某些情况下,使用闭包可能很有用。例如,当指定 visible
并且你想要在它评估为 false
的情况下阻止 value
计算时
echo DetailView::widget([
'model' => $model,
'attributes' => [
[
'attribute' => 'owner',
'value' => function ($model) {
return $model->owner->name;
},
'visible' => \Yii::$app->user->can('posts.owner.view'),
],
],
]);
ListView 小部件用于显示来自 数据提供者 的数据。每个数据模型都使用指定的 视图文件 呈现。由于它开箱即用地提供了一些功能,例如分页、排序和过滤,因此它既便于向最终用户显示信息,也便于创建数据管理 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',
]);
_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
:整数,数据项在数据提供者返回的项目数组中的零索引位置。$widget
:ListView,此小部件实例。如果需要向每个视图传递更多数据,可以使用 $viewParams 属性来传递键值对,如下所示
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
'viewParams' => [
'fullView' => true,
'context' => 'main-page',
// ...
],
]);
然后,这些变量也会在视图中可用。
数据网格或 GridView 是 Yii 中最强大的小部件之一。如果您需要快速构建系统的管理部分,它非常有用。它从 数据提供者 获取数据,并使用一组 列 渲染每一行,以表格的形式呈现数据。
表格的每一行代表单个数据项的数据,而一列通常代表该项的一个属性(某些列可能对应于属性的复杂表达式或静态文本)。
使用 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 配置的 columns 属性中进行配置。根据列类型和设置,这些列能够以不同的方式呈现数据。默认类是 yii\grid\DataColumn,它代表模型属性,可以对其进行排序和过滤。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// Simple columns defined by the data contained in $dataProvider.
// Data from the model's column will be used.
'id',
'username',
// More complex one.
[
'class' => 'yii\grid\DataColumn', // can be omitted, as it is the default
'value' => function ($data) {
return $data->name; // $data['name'] for array data, e.g. using SqlDataProvider.
},
],
],
]);
请注意,如果未指定配置的 columns 部分,Yii 将尝试显示数据提供者模型的所有可能列。
可以使用不同的列类自定义网格列
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\SerialColumn', // <-- here
// you may configure additional properties here
],
除了 Yii 提供的我们将在下面回顾的列类之外,您还可以创建自己的列类。
每个列类都扩展自 yii\grid\Column,因此在配置网格列时,您可以设置一些通用选项。
content 允许您传递一个有效的 PHP 回调,该回调将返回一行的值。格式如下
function ($model, $key, $index, $column) {
return 'a string';
}
您可以通过将数组传递给以下内容来指定各种容器 HTML 选项
数据列 用于显示和排序数据。它是默认的列类型,因此在使用它时可以省略指定类。
数据列的主要设置是其 format 属性。它的值对应于 formatter
应用程序组件 中的方法,默认情况下该方法是 Formatter
echo GridView::widget([
'columns' => [
[
'attribute' => 'name',
'format' => 'text'
],
[
'attribute' => 'birthday',
'format' => ['date', 'php:Y-m-d']
],
'created_at:datetime', // shortcut format
[
'label' => 'Education',
'attribute' => 'education',
'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'],
'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null]
],
],
]);
在上面,text
对应于 yii\i18n\Formatter::asText()。列的值作为第一个参数传递。在第二个列定义中,date
对应于 yii\i18n\Formatter::asDate()。列的值再次作为第一个参数传递,而 'php:Y-m-d' 用作第二个参数值。
有关可用格式化程序的列表,请参见 关于数据格式化的部分。
为了配置数据列,还有一个在 columns 的 API 文档中描述的快捷格式。
使用 filter 和 filterInputOptions 来控制筛选器输入的 HTML。
默认情况下,列标题由 yii\data\Sort::link() 呈现。可以使用 yii\grid\Column::$header 进行调整。要更改标题文本,您应该设置 yii\grid\DataColumn::$label,如上面的示例所示。默认情况下,标签将从数据模型中填充。有关更多详细信息,请参见 yii\grid\DataColumn::getHeaderCellLabel()。
操作列 显示操作按钮,例如更新或删除,用于每一行。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\ActionColumn',
// you may configure additional properties here
],
您可以配置的可用属性是
{view}
将被回调 buttons['view']
的结果替换。如果找不到回调,则该令牌将被空字符串替换。默认令牌是 {view} {update} {delete}
。buttons 是一个按钮渲染回调数组。数组键是按钮名称(不带大括号),而值是相应的按钮渲染回调。回调应使用以下签名
function ($url, $model, $key) {
// return the button HTML code
}
在上面的代码中,$url
是列为按钮创建的 URL,$model
是当前行正在渲染的模型对象,而 $key
是数据提供者数组中模型的键。
visibleButtons 是每个按钮的可见性条件数组。数组键是按钮名称(不带大括号),而值是布尔值 true
/false
或匿名函数。当按钮名称未在此数组中指定时,它将默认显示。回调必须使用以下签名
function ($model, $key, $index) {
return $model->status === 'editable';
}
或者您可以传递一个布尔值
[
'update' => \Yii::$app->user->can('update')
]
复选框列 显示一列复选框。
要将 CheckboxColumn 添加到 GridView,请将其添加到 columns 配置中,如下所示
echo GridView::widget([
'id' => 'grid',
'dataProvider' => $dataProvider,
'columns' => [
// ...
[
'class' => 'yii\grid\CheckboxColumn',
// you may configure additional properties here
],
],
用户可以单击复选框以选择网格的行。可以通过调用以下 JavaScript 代码来获取选定的行
var keys = $('#grid').yiiGridView('getSelectedRows');
// keys is an array consisting of the keys associated with the selected rows
序列列 从 1
开始渲染行号,并向前递增。
用法与以下内容一样简单
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'], // <-- here
// ...
注意:此部分正在开发中。
为了过滤数据,GridView 需要一个 模型 来表示搜索条件,该条件通常取自 GridView 表格中的过滤器字段。当使用 活动记录 时,一种常见的做法是创建一个搜索模型类,该类提供所需的功能(可以使用 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()
{
// bypass scenarios() implementation in the parent class
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;
}
}
您可以在控制器中使用此函数为 GridView 获取数据提供者
$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' => [
// ...
],
]);
大多数时候,使用 GridView 标题过滤器就足够了,但如果您需要单独的过滤器表单,也可以轻松地添加它。您可以创建具有以下内容的部分视图 _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.php
视图中,如下所示
<?= $this->render('_search', ['model' => $searchModel]) ?>
注意:如果您使用 Gii 生成 CRUD 代码,则默认情况下会生成单独的过滤器表单 (
_search.php
),但在index.php
视图中已注释掉。取消注释它,它就可以使用了!
当您需要按 GridView 中未显示的字段进行过滤,或者用于特殊过滤条件(如日期范围)时,单独的过滤器表单非常有用。为了按日期范围进行过滤,我们可以将非数据库属性 createdFrom
和 createdTo
添加到搜索模型中
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') ?>
在 GridView 中显示活动记录时,您可能会遇到显示相关列值的情况,例如帖子作者的姓名,而不是仅显示他的 id
。您可以通过在 yii\grid\GridView::$columns 中将属性名称定义为 author.name
来做到这一点,其中 Post
模型具有名为 author
的关系,而作者模型具有属性 name
。然后,GridView 将显示作者的姓名,但默认情况下不会启用排序和过滤。您必须调整上节中介绍的 PostSearch
模型以添加此功能。
要启用对相关列的排序,您必须联接相关表格并将排序规则添加到数据提供者的 Sort 组件中
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// join with relation `author` that is a relation to the table `users`
// and set the table alias to be `author`
$query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
// since version 2.0.7, the above line can be simplified to $query->joinWith('author AS author');
// enable sorting for the related column
$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()
等)中使用关系名称。例如,如果您对作者关系表使用别名
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], ];
此外,在指定用于排序的 defaultOrder 时,您需要使用关系名称,而不是别名
$dataProvider->sort->defaultOrder = ['author.name' => SORT_ASC];
信息:有关
joinWith
和后台执行的查询的更多信息,请查看 关于与关系联接的活动记录文档。
还有一种方法可以更快、更有效 - 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
然后您需要创建将代表此视图的 ActiveRecord
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 function attributeLabels()
{
return [
// define here your attribute labels
];
}
}
之后,您可以将此 UserView ActiveRecord 与搜索模型一起使用,而无需额外指定排序和过滤属性。所有属性都将开箱即用。请注意,这种方法有几个优点和缺点
isActive
、isDeleted
或其他将影响 UI 的方法,您将需要在此类中复制它们。您可以在一个页面上使用多个网格视图,但需要一些额外的配置才能使它们互不干扰。当使用多个网格视图实例时,您必须为生成的排序和分页链接配置不同的参数名称,以便每个网格视图都有其自己的独立排序和分页。您可以通过设置数据提供者的 sortParam 和 pageParam 来实现 sort 和 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,
]);
Pjax 小部件允许您更新页面的某个部分,而不是重新加载整个页面。您可以使用它来仅在使用过滤器时更新 GridView 内容。
use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin([
// PJax options
]);
Gridview::widget([
// GridView options
]);
Pjax::end();
Pjax 也适用于 Pjax 小部件内部的链接以及 Pjax::$linkSelector 指定的链接。但这可能对 ActionColumn 的链接来说是一个问题。为了防止这种情况,当您编辑 ActionColumn::$buttons 属性时,请在链接中添加 HTML 属性 data-pjax="0"
。
从 2.0.5 版本开始,Gii 的 CRUD 生成器有一个名为 $enablePjax
的选项,可以通过 Web 界面或命令行使用。
yii gii/crud --controllerClass="backend\\controllers\PostController" \
--modelClass="common\\models\\Post" \
--enablePjax=1
它生成一个 Pjax 小部件,它包装 GridView 或 ListView 小部件。
发现错别字或您认为此页面需要改进?
在 github 上编辑它 !
在“单独的过滤器表单”部分的最后一行代码中有一个错误
<?= $form->field($model, 'creationFrom') ?> <?= $form->field($model, 'creationTo') ?>
应该是
<?= $form->field($model, 'createdFrom') ?> <?= $form->field($model, 'createdTo') ?>
对我来说,ListView 和 GridView 最有用的地方是通过某种链接或按钮打开一个“详细”屏幕。除了“操作”列之外,这并没有得到太多关注。大多数情况下,您并不想要一个新列,而只是文本中的一个链接供他们点击。我相信上面提到的其中一项功能可以做到这一点,但它并不清楚到底是什么或如何做到。
请 注册 或 登录 才能评论。