gridview yii2_使用GridView和ListView在Yii 2中渲染数据

gridview yii2

In my previous article about Yii 2.0, I introduced the ActiveRecord implementation. Once you have some data in your database you’ll want to be able to show it. Yii uses DataProviders to interact with data sources and it provides some widgets to output the data. Of these, the ListView and GridView provide the most functionality.

在上一篇有关Yii 2.0的文章中,我介绍了ActiveRecord实现。 一旦数据库中有一些数据,您将希望能够显示它。 Yii使用DataProviders与数据源进行交互,并提供一些小部件来输出数据。 其中,ListView和GridView提供最多的功能。

Yii logo

这个例子 (The example)

I’m going to work with the database example that I introduced in my previous article again. Not very original, but quite useful as an example; a blog like SitePoint.

我将再次使用在上一篇文章中介绍的数据库示例。 不是很原始,但是作为示例很有用; 像SitePoint这样的博客。

SitePoint Yii 2.0 blog example

A small wrap-up of this database design and its Yii models which I’ll be using in this example:

我将在此示例中使用此数据库设计及其Yii模型的小结:

  • The Authors model has one relation method call getArticles() that provides an Articles[] attribute to the model.

    Authors模型具有一个名为getArticles()关联方法,该方法为模型提供了Articles[]属性。

  • The Articles model has one relation method call getAuthor() that provides the Author and a method getTags() that provides the Tags[].

    Articles模型具有一个关系方法调用getAuthor() ,该方法提供了Author ;一个方法getTags() ,提供了Tags[]

  • The Tags model has one relation method call getArticles that provides Articles[].

    Tags模型具有一种称为getArticles关系方法,该方法提供Articles[]

I won’t be using the ArticlesTags table since it is just used for an N:M relation. Of course, there is a model available for it which is used in the relation definition of the other models.

我不会使用ArticlesTags表,因为它仅用于N:M关系。 当然,有一个可用的模型可用于其他模型的关系定义中。

数据提供者 (DataProviders)

There are three different types:

有三种不同的类型:

  • The ActiveDataProvider is fed through an ActiveQuery instance and usually holds an array of models. You’ll normally use it to hold and render data that can be built from normal ActiveRecord instances with their relations.

    ActiveDataProvider通过ActiveQuery实例提供,通常包含一系列模型。 通常,您将使用它来保存和呈现可以从普通ActiveRecord实例及其关系构建的数据。

  • The ArrayDataProvider is built using an array of data. This is quite useful when building all sorts of reports based on multiple models and/or custom aggregations.

    ArrayDataProvider使用数据数组构建。 当基于多个模型和/或自定义聚合构建各种报告时,这非常有用。

  • The SqlDataProvider is a very useful one for the SQL masters among us. It is an easy way to get the data of those complex queries.

    对于我们中间SQL大师来说, SqlDataProvider是非常有用的。 这是获取那些复杂查询的数据的简便方法。

They don’t have huge differences, except slightly in views. The data provider itself is a base component that holds data and handles pagination and sorting.

它们之间没有很大的差异,只是在视图上稍有不同。 数据提供程序本身是保存数据并处理分页和排序的基本组件。

ActiveDataProvider (ActiveDataProvider)

I already explained that this is populated with an ActiveQuery object. Any model::find() will return an ActiveQuery object so creating one is quite simple.

我已经解释过,这是用ActiveQuery对象填充的。 任何model::find()都会返回一个ActiveQuery对象,因此创建一个对象非常简单。

/* A dataprovider with all articles */
$dataProvider = new ActiveDataProvider([
    'query' => Articles::find()->with('tags'),
]);

/* Get all the articles for one author by using the author relation define in Articles */
$dataProvider = new ActiveDataProvider([
    'query' => Articles::find()->with('author')->where(['Name'=>'Arno Slatius']),
]);

/* Be careful with this! */
$dataProvider = new ActiveDataProvider([
    'query' => Articles::find()->with('author')->where(['Name'=>'Arno Slatius'])->orderBy('Published'),
]);

The last example is one to be careful with, you’ll limit the abilities of your DataProvider since it can do sorting on its own. Keep this in mind, I’ll address it later on.

最后一个示例是一个要小心的示例,由于它可以自行进行排序,因此将限制DataProvider的功能。 请记住这一点,我稍后会解决。

SqlDataProvider (SqlDataProvider)

This one will gather your data based on a SQL statement. My example doesn’t really justify the use of SQL but I’ll do it anyway to show something and throw in some aggregation;

这将基于SQL语句收集您的数据。 我的示例并没有真正证明使用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'],
]);

There are good arguments to use an SQL query as input for your data provider. ActiveRecord is a very nice way to work with databases, but you might find that defining the criteria for larger databases gets somewhat complex. If you are good at writing SQL and you need a lot of joins, unions and/or aggregations you might find it easier to build an SQL query first and simply use that as an input to your DataProvider.

有很好的论据可以将SQL查询用作数据提供者的输入。 ActiveRecord是使用数据库的一种非常不错的方法,但是您可能会发现,为大型数据库定义条件变得有些复杂。 如果您擅长编写SQL,并且需要大量的联接,联合和/或聚合,则可能会发现首先构建SQL查询并简单地将其用作DataProvider的输入会更容易。

ArrayDataProvider (ArrayDataProvider)

This might be the most useful component of the bunch. Anything that you’d normally put in a table that requires a bit more work to compose is well suited for an array data provider. The documentation uses quite a simple example inserting a few models in an array like so:

这可能是最有用的组件。 通常放在表中的任何内容都需要做更多的工作才能很好地适用于数组数据提供程序。 该文档使用一个非常简单的示例在数组中插入几个模型,如下所示:

$dataProvider = new ArrayDataProvider([
    'allModels' => Authors::find()->all(),
]);

That’ll fill the provider with all the authors. Very simple indeed, but let’s make it more practical and do something that this component is quite useful for; I want to output a list of all authors with their article count and last published date. I’m going to do this by extending the ArrayDataProvider and creating my own. I use the init() function which is available on almost all components. This is called when the class is created and used (in this case) to prepare the data in the provider.

这将使提供者全部充满。 确实很简单,但是让我们使其更实用,并做一些使该组件有用的操作; 我想输出所有作者的列表以及他们的文章数和上次发布日期。 我将通过扩展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,
			];
		}
	}
}

You can see that the variable containing all rows for the table to be shown, $this->allModels, is filled with the data we need.

您可以看到包含要显示的表的所有行的变量$this->allModels充满了我们需要的数据。

可视化数据 (Visualizing the data)

We’ve got a data provider but now we want to render what’s in there, right? Yii provides two components to visualize the data put into the data provider.

我们有一个数据提供程序,但是现在我们想渲染其中的内容,对不对? Yii提供了两个组件来可视化放入数据提供程序中的数据。

  • The GridView will put the data in an HTML table. If properly configured, it’ll automatically add headers that you can click to change the sorting, pagination to limit the number of items shown at once to the user and a summary showing the total number of results available.

    GridView会将数据放入HTML表中。 如果配置正确,它将自动添加标题,您可以单击这些标题以更改排序,分页以限制一次向用户显示的项目数,以及摘要显示可用结果的总数。

  • The ListView allows you to specify a partial view with which you can render each of the models in the data provider in a specific way. A very common way to go about this is using this to render the content of <li> elements of an ordered or unordered list.

    ListView允许您指定局部视图,通过该局部视图可以以特定方式呈现数据提供程序中的每个模型。 解决此问题的一种非常常见的方法是使用它来呈现有序列表或无序列表的<li>元素的内容。

It’s probably best illustrated with a few examples. Let’s assume the following data provider:

最好用几个例子来说明。 假设以下数据提供者:

/* A dataprovider with all articles */
$dataProvider = new ActiveDataProvider([
    'query' => Articles::find()->with('tags','authors'),
]);

Note that I immediately make ActiveRecord execute a join of the Articles on the ArticleTags and Tags table by specifying the with() method. This is known as ‘eager loading’, making the related data available immediately. When done without the with() you’d still be able to use the data available from the author and tags relation in your views, but it would be loaded run time, also known as ‘lazy loading’. If you know you’re going to use related data, use with(). Eager loading performs a lot better than lazy loading.

请注意,我通过指定with()方法立即使ActiveRecord在ArticleTags和Tags表上执行Articles的联接。 这称为“紧急加载”,使相关数据立即可用。 在没有with()情况下完成操作之后with()您仍然可以在视图中使用来自authortags关系的可用数据,但是它将被加载运行时,也称为“延迟加载”。 如果您知道将要使用相关数据,请使用with() 。 较早的加载比延迟的加载好得多。

In the view, we’d render a table with a GridView. I’m showing a few columns in increasing complexity, a simple list of the article first:

在视图中,我们将使用GridView渲染表。 我将以越来越复杂的方式显示几列,首先是文章的简单列表:

<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        'ID',
        'Author',
        'Title',
        'Published:date',
    ],
]); ?>

Which will look like this:

看起来像这样:

Yii 2.0 GridView Blog Articles Example

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.

我确实承认,我定义了6页的页面大小和3列可以对其进行排序的内容,这有点作弊。 稍后再讨论。 请注意顶部的摘要,列标题中的排序链接和底部的寻呼机。 在适用的情况下,所有内容都以本地化格式(对我来说是荷兰语)格式化。 我不需要其他代码即可处理链接或下一页的工作。 链接全部由窗口小部件自动生成,并且动作由DataProvider处理。 该组件使开箱即用的生活变得非常轻松。

Since I joined the articles with other tables, we can use that data as well in a very easy table.column manner. Formatting of the data can also be customized using anonymous functions:

由于我将文章与其他表一起加入,因此我们也可以以非常简单的table.column方式使用该数据。 数据格式也可以使用匿名功能进行自定义:

<?= GridView::widget([
		'dataProvider' => $dataProvider,
        'columns' => [
	        'Title',
	        'author.Name',
	        [
	            'attribute' => 'author.Twitter',
	            'type' => 'html',
	            'value' => function($model) {
		            return Html::link('@' . $model->author->Twitter, 'https://twitter.com/' . $model->author->Twitter);
	            }
	        ],
	        [
		        'attribute' => 'tags',
		        'value' => function($model) {
			        return implode(', ', ArrayHelper::map($model->tags, 'ID', 'Tag'));
			    }
			],
			'Published:date',
		],
	]); ?>

The key, when defining the output for the columns, is to remember that each extends from yii\grid\Column so always look back at that class to see all the attributes and functions you can use. For instance, yii\grid\DataColumn has a $footer attribute. Add that to the configuration array of a column to set the footer text, and don’t forget to set showFooter to true in the GridView.

定义列的输出时,关键是要记住每个列都是从yii\grid\Column扩展的,因此请始终回顾该类以查看可以使用的所有属性和函数。 例如, yii\grid\DataColumn具有$footer属性。 将其添加到列的配置数组中以设置页脚文本,并且不要忘记在GridView中将showFooter设置为true。

The GridView actually has quite a few extra attributes through which you can configure it. I’ll use another example:

GridView实际上具有许多额外的属性,您可以通过它们配置它。 我将使用另一个示例:

<?= GridView::widget([
		'dataProvider' => $dataProvider,
        'columns' => [
        ...
        ],
        'layout' => '{summary}{items}{pager}',
		'filterPosition' => FILTER_POS_FOOTER,
		'rowOptions' => function ($model, $key, $index, $grid) {
		},
		'emptyText' => '-',
		'showFooter' => true,
    ]); ?>

The layout attribute is a very useful one. It allows you to change the way the basic elements appear. You can add {summary}, {errors}, {items}, {sorter}, {pager} some even multiple times; you might want a pager above and below the items list, the same might go for the summary which basically shows the total number of results and the number of currently shown results. Errors are a list of errors that the filter outputs (if any). filterPosition allows you to move the filter to the bottom, or inside the body. Normally it would be included in the header part of the table, etc.

layout属性是一个非常有用的属性。 它允许您更改基本元素的显示方式。 您甚至可以多次添加{summary}, {errors}, {items}, {sorter}, {pager} ; 您可能希望在项目列表的上方和下方有一个寻呼机,摘要也可能会使用相同的内容,它基本上显示了结果的总数和当前显示的结果数。 错误是过滤器输出的错误列表(如果有)。 filterPosition允许您将过滤器移动到底部或体内。 通常,它将包含在表的标题部分中,依此类推。

自定义排序和分页 (Customizing Sorting and Paging)

The GridView will do sorting and pagination for you by default. Its functionality is actually provided through configuration of the yii\data\BaseDataProvider which can be initialized by supplying additional parameters during the class’ initialization. Let’s start with simple pagination; by default, it is set to defaultPageSize which normally gives 20 results per page. Change it by supplying a pageSize, or use it to display everything and turn off pagination:

默认情况下,GridView将为您进行排序和分页。 实际上,它的功能是通过yii\data\BaseDataProvider配置提供的,可以通过在类的初始化期间提供其他参数来进行初始化。 让我们从简单的分页开始; 默认情况下,它设置为defaultPageSize ,通常每页给出20个结果。 通过提供pageSize更改,或使用它显示所有内容并关闭分页:

/* 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
    ],
...

Sorting has quite a few more options which depend on the data you supply and display. First, you can customize the sorting. 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.

排序还有很多其他选项,具体取决于您提供和显示的数据。 首先,您可以自定义排序。 您可以提供多个属性以对每一列进行排序。 当您使用GridView时,您可能会发现默认排序处理有时会在更复杂的属性或使用未命名函数输出的值上失败。 在这些情况下,提供排序属性也有帮助。

Let’s go over some code:

让我们来看一些代码:

$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.

您可能会猜到,如果要渲染GridView,则defaultOrder发生更改。 在此示例中,顺序将以“已发布”降序,然后是“最后编辑”降序。

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.

attributes将包含GridView列中所有可排序属性的列表(此处的属性名称应与GridView中的属性名称匹配)。 您可以独立定义升序和降序结果的排序方式–同样,可以在数据库中的多个列上完成此操作。

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.

要注意的一件事是,为了使分页正常工作,DataProvider需要知道可用结果的总数。 默认情况下, ActiveDataProviderSqlDataProvider可以使用数据库查询来执行此操作。 如果使用ArrayDataProvider ,则可能需要完成一些其他工作,具体取决于填充提供程序的方式。

结论 (Conclusion)

The ListView and GridView are very practical widgets which allow you to quickly show the data that you want. If you want even more from your GridView, then be sure to check out the ‘GridView on steroids’ made by Kartik Visweswaran. This adds a lot of additional functionality to your grids allowing the user to fully customize the way the data is shown. Be sure to check out all the other components from Kartik as well!

ListView和GridView是非常实用的小部件,可让您快速显示所需的数据。 如果您想从GridView中获得更多信息,请务必查看由Kartik Visweswaran制造的“ 类固醇中GridView ”。 这为网格增加了许多附加功能,使用户可以完全自定义数据的显示方式。 请务必同时检查Kartik的所有其他组件!

Are there more Yii 2.0 topics that you would like to see covered? Suggestions are welcome!

您是否希望涵盖更多的Yii 2.0主题? 欢迎提出建议!

翻译自: https://www.sitepoint.com/rendering-data-in-yii-2-with-gridview-and-listview/

gridview yii2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值