В моей предыдущей статье о Yii 2.0 я представил реализацию ActiveRecord . Если у вас есть данные в вашей базе данных, вы захотите их показать. Yii использует DataProviders для взаимодействия с источниками данных и предоставляет некоторые виджеты для вывода данных. Из них ListView и GridView предоставляют наибольшую функциональность.
Пример
Я собираюсь работать с примером базы данных, который я снова представил в моей предыдущей статье. Не очень оригинально, но довольно полезно в качестве примера; блог, как SitePoint.
Небольшое завершение этого дизайна базы данных и ее моделей Yii, которые я буду использовать в этом примере:
- Модель
Authors
имеет один метод вызова методаgetArticles()
который предоставляет атрибутArticles[]
модели. - Модель
Articles
имеет один метод вызова методаgetAuthor()
который предоставляетAuthor
и методgetTags()
который предоставляетTags[]
. - Модель
Tags
имеет один метод вызова методаgetArticles
который предоставляетArticles[]
.
Я не буду использовать таблицу ArticlesTags, так как она используется только для отношения N: M. Конечно, существует модель, которая используется для определения отношений других моделей.
DataProviders
Есть три разных типа:
-
ActiveDataProvider
передается через экземпляр ActiveQuery и обычно содержит массив моделей. Обычно вы будете использовать его для хранения и визуализации данных, которые могут быть построены из обычных экземпляров ActiveRecord с их отношениями. -
ArrayDataProvider
построен с использованием массива данных. Это очень полезно при создании всевозможных отчетов на основе нескольких моделей и / или пользовательских агрегатов. -
SqlDataProvider
очень полезен для мастеров SQL среди нас. Это простой способ получить данные этих сложных запросов.
У них нет огромных различий, за исключением незначительных взглядов. Сам провайдер данных является базовым компонентом, который хранит данные и обрабатывает нумерацию страниц и сортировку.
ActiveDataProvider
Я уже объяснил, что это заполнено объектом 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'=>]), ]); /* Be careful with this! */ $dataProvider = new ActiveDataProvider([ 'query' => Articles::find()->with('author')->where(['Name'=>])->orderBy('Published'), ]);
Последний пример, с которым следует быть осторожным, вы ограничите возможности своего DataProvider, поскольку он может выполнять сортировку самостоятельно. Имейте это в виду, я рассмотрю это позже.
SqlDataProvider
Этот будет собирать ваши данные на основе инструкции 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' => ], ]);
Есть хорошие аргументы для использования SQL-запроса в качестве входных данных для вашего поставщика данных. ActiveRecord — очень хороший способ работы с базами данных, но вы можете обнаружить, что определение критериев для больших баз данных становится несколько сложным. Если вы хорошо пишете SQL и вам нужно много объединений, объединений и / или агрегатов, вам может быть проще сначала создать запрос 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
, заполнена данными, которые нам нужны.
Визуализация данных
У нас есть провайдер данных, но теперь мы хотим показать, что там, верно? Yii предоставляет два компонента для визуализации данных, помещаемых в поставщик данных.
-
GridView
поместит данные в таблицу HTML. При правильной настройке он автоматически добавит заголовки, по которым можно щелкнуть, чтобы изменить сортировку, нумерацию страниц, чтобы ограничить количество отображаемых элементов сразу для пользователя, и сводную информацию, показывающую общее количество доступных результатов. -
ListView
позволяет вам указать частичное представление, с помощью которого вы можете отображать каждую из моделей в поставщике данных определенным образом. Очень распространенный способ добиться этого — использовать его для визуализации содержимого элементов<li>
упорядоченного или неупорядоченного списка.
Это, вероятно, лучше всего проиллюстрировано несколькими примерами. Давайте предположим, что следующий поставщик данных:
/* A dataprovider with all articles */ $dataProvider = new ActiveDataProvider([ 'query' => Articles::find()->with('tags','authors'), ]);
Обратите внимание, что я немедленно заставляю ActiveRecord выполнить соединение статей в таблице ArticleTags и Tags, указав метод with()
. Это называется «готовая загрузка», что делает соответствующие данные доступными немедленно. Когда вы обойдетесь без использования with()
вы все равно сможете использовать данные, доступные из отношения author
и tags
в ваших представлениях, но они будут загружены во время выполнения, также известное как «отложенная загрузка». Если вы знаете, что собираетесь использовать связанные данные, используйте with()
. Стремительная загрузка выполняется намного лучше, чем ленивая загрузка.
В представлении мы бы визуализировали таблицу с GridView. Я показываю несколько столбцов в возрастающей сложности, сначала простой список статей:
<?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ 'ID', 'Author', 'Title', 'Published:date', ], ]); ?>
Который будет выглядеть так:
Я признаю, что немного обманул, определив размер страницы в 6 и три столбца, по которым он может сортироваться; Подробнее об этом позже. Обратите внимание на сводку вверху, ссылки сортировки в заголовках столбцов и пейджер внизу. Все отформатировано в локализованном формате (голландский для меня), где это применимо. Мне не нужен был дополнительный код, чтобы заставить работать ссылки для сортировки или работы следующих страниц. Все ссылки автоматически генерируются виджетом, а действия обрабатываются DataProvider. Этот компонент действительно облегчает жизнь из коробки.
Поскольку я соединил статьи с другими таблицами, мы можем использовать эти данные также очень просто в виде таблицы. Форматирование данных также можно настроить с помощью анонимных функций:
<?= 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', ], ]); ?>
При определении выходных данных для столбцов yii\grid\Column
помнить, что каждый из них простирается от yii\grid\Column
поэтому всегда оглядывайтесь на этот класс, чтобы увидеть все атрибуты и функции, которые вы можете использовать. Например, yii\grid\DataColumn
имеет атрибут $footer
. Добавьте это к массиву конфигурации столбца, чтобы установить текст showFooter
колонтитула, и не забудьте установить для showFooter
значение true в GridView.
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
которая может быть инициализирована путем предоставления дополнительных параметров во время инициализации класса. Давайте начнем с простой нумерации страниц; по умолчанию установлено значение 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 ], ...
У сортировки есть еще несколько опций, которые зависят от данных, которые вы предоставляете и отображаете. Во-первых, вы можете настроить сортировку. Вы можете предоставить несколько атрибутов для сортировки для каждого столбца. При использовании GridView вы можете обнаружить, что обработка сортировки по умолчанию иногда дает сбой в более сложных атрибутах или в значениях, которые вы выводите, используя неназванные функции. В этих ситуациях предоставление атрибутов сортировки также помогает.
Давайте рассмотрим некоторый код:
$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 ... ], ], ]);
defaultOrder
изменил, как вы можете догадаться, начальный порядок GridView, если он будет отображен. В этом примере порядок будет «Опубликован» по убыванию, а «LastEdited» — по убыванию.
attributes
будут содержать список всех сортируемых атрибутов из столбцов GridView (имена атрибутов здесь должны совпадать с именами атрибутов в GridView). Вы можете самостоятельно определить, как будут отсортированы восходящий и нисходящий результаты — опять же, это можно сделать для нескольких столбцов в вашей БД.
Следует отметить, что для работы с нумерацией страниц DataProvider необходимо знать общее количество доступных результатов. ActiveDataProvider
и SqlDataProvider
могут делать это по умолчанию, используя запросы к базе данных. Если вы используете ArrayDataProvider
, вам может потребоваться выполнить дополнительную работу в зависимости от того, как вы заполняете провайдера.
Вывод
ListView и GridView — очень практичные виджеты, которые позволяют быстро отображать нужные данные. Если вы хотите еще больше от своего GridView, то обязательно посмотрите « GridView на стероидах », созданный Kartik Visweswaran. Это добавляет множество дополнительных функциональных возможностей к вашим сеткам, позволяя пользователю полностью настроить способ отображения данных. Обязательно ознакомьтесь со всеми другими компонентами от Kartik!
Есть ли еще темы по Yii 2.0, которые вы бы хотели охватить? Предложения приветствуются!