Yii はデータを表示するために使うことが出来る一連の ウィジェット を提供しています。 DetailView は、単一のレコードのデータを表示するのに使うことが出来ます。 それに対して、ListView と GridView は、複数のデータ・レコードをリストまたはテーブルで表示することが出来るもので、 ページネーション、並べ替え、フィルタリングなどの機能を提供するものです。
DetailView は単一のデータ モデル の詳細を表示します。
モデルを標準的な書式で表示する場合 (例えば、全てのモデル属性をそれぞれテーブルの一行として表示する場合) に最も適しています。 モデルは yii\base\Model またはそのサブ・クラス、例えば アクティブ・レコード のインスタンスか、連想配列かのどちらかにすることが出来ます。
DetailView は yii\widgets\DetailView::$attributes プロパティを使って、モデルのどの属性が表示されるべきか、また、どういうフォーマットで表示されるべきかを決定します。 利用できるフォーマットのオプションについては、フォーマッタのセクション を参照してください。
次に DetailView の典型的な用例を示します。
echo DetailView::widget([
'model' => $model,
'attributes' => [
'title', // title 属性 (平文テキストで)
'description:html', // description 属性は HTML としてフォーマットされる
[ // モデルの所有者の名前
'label' => '所有者',
'value' => $model->owner->name,
'contentOptions' => ['class' => 'bg-red'], // 値のタグをカスタマイズする HTML 属性
'captionOptions' => ['tooltip' => 'Tooltip'], // ラベルのタグをカスタマイズする HTML 属性
],
'created_at:datetime', // 作成日時は 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 ウィジェットは、データ・プロバイダ からのデータを表示するのに使用されます。 各データ・モデルは指定された ビュー・ファイル を使って表示されます。 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
: mixed - データ・アイテムと関連付けられたキーの値。$index
: integer - データ・プロバイダによって返されるアイテムの配列の 0 から始まるインデックス。$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'],
// $dataProvider に含まれるデータによって定義される単純なカラム
// モデルのカラムのデータが使われる
'id',
'username',
// 複雑なカラム定義
[
'class' => 'yii\grid\DataColumn', // 省略可。これがデフォルト値。
'value' => function ($data) {
return $data->name; // 配列データの場合は $data['name']。例えば、SqlDataProvider を使う場合。
},
],
],
]);
構成情報の columns の部分が指定されない場合は、Yii は、 データ・プロバイダのモデルの表示可能な全てのカラムを表示しようとすることに注意してください。
グリッドのカラムは、いろいろなカラム・クラスを使うことでカスタマイズすることが出来ます。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\SerialColumn', // <-- ここ
// ここで追加のプロパティを構成することが出来ます
],
Yii によって提供されるカラム・クラスを以下で見ていきますが、それらに加えて、あなた自身のカラム・クラスを作成することも出来ます。
全てのカラム・クラスは yii\grid\Column を拡張するものですので、グリッドのカラムを構成するときに設定できる 共通のオプションがいくつかあります。
content によって、行のデータを返す有効な PHP コールバックを渡すことが出来ます。書式は以下の通りです。
function ($model, $key, $index, $column) {
return '文字列';
}
下記のオプションに配列を渡して、コンテナ要素のさまざまな 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' => '教育',
'attribute' => 'education',
'filter' => ['0' => '初等教育', '1' => '中等教育', '2' => '高等教育'],
'filterInputOptions' => ['prompt' => '全ての教育', 'class' => 'form-control', 'id' => null]
],
],
]);
上記において、text
は yii\i18n\Formatter::asText() に対応し、カラムの値が最初の引数として渡されます。
二番目のカラムの定義では、date
が yii\i18n\Formatter::asDate() に対応します。
カラムの値が、ここでも、最初の引数として渡され、'php:Y-m-d' が二番目の引数の値として渡されます。
利用できるフォーマッタの一覧については、データのフォーマット のセクションを参照してください。
データカラムを構成するためには、ショートカット形式を使うことも出来ます。 それについては、columns の API ドキュメントで説明されています。
フィルタ・インプットの HTML を制御するためには、filter と filterInputOptions を使用して下さい。
デフォルトでは、カラム・ヘッダは 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',
// ここで追加のプロパティを構成することが出来ます
],
構成が可能なプロパティは、以下の通りです。
{view}
というトークンは、buttons['view']
のコールバックの結果によって置き換えられます。
コールバックが見つからない場合は、トークンは空文字列によって置き換えられます。デフォルトのテンプレートは {view} {update} {delete}
です。buttons はボタン表示コールバックの配列です。 配列のキーはボタンの名前 (波括弧を除く) であり、値は対応するボタン表示コールバックです。コールバックは下記のシグニチャを使わなければなりません。
function ($url, $model, $key) {
// ボタンの HTML コードを返す
}
上記のコードで、$url
はカラムがボタンのために生成する URL、$model
は現在の行に表示されるモデル・オブジェクト、
そして $key
はデータ・プロバイダの配列の中にあるモデルのキーです。
visibleButtons は、各ボタンの可視性の条件を定義する配列です。
配列のキーはボタンの名前 (波括弧を除く) であり、値は真偽値 true
/false
または無名関数です。
ボタンの名前がこの配列の中で指定されていない場合は、デフォルトで、ボタンが表示されます。
コールバックは次のシグニチャを使わなければなりません。
function ($model, $key, $index) {
return $model->status === 'editable';
}
または、真偽値を渡すことも出来ます。
[
'update' => \Yii::$app->user->can('update')
]
チェックボックス・カラム はチェックボックスのカラムを表示します。
GridView に CheckboxColumn を追加するためには、以下のようにして、columns 構成情報にカラムを追加します。
echo GridView::widget([
'id' => 'grid',
'dataProvider' => $dataProvider,
'columns' => [
// ...
[
'class' => 'yii\grid\CheckboxColumn',
// ここで追加のプロパティを構成することが出来ます
],
],
ユーザはチェックボックスをクリックして、グリッドの行を選択することが出来ます。 選択された行は、次の JavaScript コードを呼んで取得することが出来ます。
var keys = $('#grid').yiiGridView('getSelectedRows');
// keys は選択された行と関連付けられたキーの配列
シリアルカラム は、1
から始まる行番号を表示します。
使い方は、次のように、とても簡単です。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'], // <-- ここ
// ...
補足: このセクションはまだ執筆中です。
データをフィルタリングするためには、GridView は検索基準を表す モデル を必要とします。
検索基準は、通常は、グリッド・ビューのテーブルのフィルタのフィールドから取得されます。
アクティブ・レコード を使用している場合は、必要な機能を提供する検索用のモデル・クラスを
作成するのが一般的なプラクティスです (あなたに代って 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;
}
}
ヒント: フィルタのクエリを構築する方法を学ぶためには、クエリ・ビルダ、 中でも特に フィルタ条件 を参照してください。
この search()
メソッドをコントローラで使用して、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' => [
// ...
],
]);
たいていの場合はグリッド・ビューのヘッダのフィルタで十分でしょう。しかし、独立したフィルタのフォームが必要な場合でも、
簡単に追加することができます。まず、以下の内容を持つパーシャル・ビュー _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
ビューの中ではコメント・アウトされています。コメントを外せば、すぐに使うことが出来ます。
独立したフィルタ・フォームは、グリッド・ビューに表示されないフィールドによってフィルタをかけたり、
または日付の範囲のような特殊なフィルタ条件を使う必要があったりする場合に便利です。
日付の範囲によってフィルタする場合は、DB には存在しない 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
ではなく、
投稿者の名前のような関連するカラムの値を表示するという場合に遭遇するかも知れません。
Post
モデルが author
という名前のリレーションを持っていて、その投稿者のモデルが name
という属性を持っているなら、
yii\grid\GridView::$columns の属性名を author.name
と定義します。
そうすれば、GridView が投稿者の名前を表示するようになります。ただし、並べ替えとフィルタリングは、デフォルトでは有効になりません。
これらの機能を追加するためには、前の項で導入した PostSearch
モデルを修正しなければなりません。
リレーションのカラムによる並べ替えを有効にするためには、リレーションのテーブルを結合し、 データ・プロバイダの Sort コンポーネントに並べ替えの規則を追加します。
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// リレーション `author` を結合します。これはテーブル `users` に対するリレーションであり、
// テーブル・エイリアスを `author` とします。
$query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
// バージョン 2.0.7 以降では、上の行は $query->joinWith('author AS author'); として単純化することが出来ます。
// リレーションのカラムによる並べ替えを有効にします。
$dataProvider->sort->attributes['author.name'] = [
'asc' => ['author.name' => SORT_ASC],
'desc' => ['author.name' => SORT_DESC],
];
// ...
フィルタリングも上記と同じ joinWith の呼び出しを必要とします。また、次のように、attributes
と rules
の中で、検索可能なカラムを追加で定義する必要があります。
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
というエイリアスを使う場合は、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 ビューです。 例えば、ユーザとユーザのプロファイルを一緒にグリッド・ビューに表示する必要がある場合、次のような 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 [
// ここで規則を定義
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
// ここで属性のラベルを定義
];
}
}
このようにした後は、この UserView アクティブ・レコードを検索用のモデルとともに使うことが出来ます。並べ替えやフィルタリングの属性を追加で定義する必要はありません。 全ての属性がそのままで動作します。この手法にはいくつかの長所と短所があることに注意してください。
isActive
や isDeleted
などのような UI に影響するメソッドがある場合は、それらをこのクラスの中に複製する必要があります。一つのページで二つ以上のグリッド・ビューを使うことが出来ますが、 お互いが干渉しないように、追加の構成がいくつか必要になります。 グリッド・ビューの複数のインスタンスを使う場合は、並べ替えとページネーションのリンクが違うパラメータ名を持って生成されるように構成して、 それぞれのグリッド・ビューが独立した並べ替えとページネーションを持つことが出来るようにしなければなりません。 そのためには、データ・プロバイダの sort と pagination インスタンスの sortParam と pageParam を設定します。
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>ユーザ</h1>';
echo GridView::widget([
'dataProvider' => $userProvider,
]);
echo '<h1>投稿</h1>';
echo GridView::widget([
'dataProvider' => $postProvider,
]);
Pjax ウィジェットを使うと、ページ全体をリロードせずに、 ページの一部分だけを更新することが出来ます。 これを使うと、フィルタを使うときに、GridView の中身だけを更新することが出来ます。
use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin([
// PJax のオプション
]);
Gridview::widget([
// GridView のオプション
]);
Pjax::end();
Pjax は、Pjax ウィジェットの内側にあるリンク、および、Pjax::$linkSelector
で指定されているリンクに対しても動作します。
しかし、これは ActionColumn のリンクに対しては問題となり得ます。
この問題を防止するためには、ActionColumn::$buttons
プロパティを編集して data-pjax="0"
という HTML 属性を追加します。
バージョン 2.0.5 以降、Gii の CRUD ジェネレータでは $enablePjax
というオプションがウェブ・インタフェイスまたはコマンドラインで使用可能になっています。
yii gii/crud --controllerClass="backend\\controllers\PostController" \
--modelClass="common\\models\\Post" \
--enablePjax=1
これによって、GridView または ListView を囲む Pjax ウィジェットが生成されます。
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.