記事の表示
==========

このブログアプリケーションでは、記事はリスト形式での表示と単独での表示が可能です。前者は `index` 操作として実装され、後者は `view` 操作として実装されています。このセクションでは、初期の要求を満たすように両方の操作をカスタマイズします。


`view` 操作のカスタマイズ
------------------------

`view` 操作は `PostController` の `actionView()` メソッドで実装されています。表示内容は `view` というビューで生成されます。ビューファイルは `/wwwroot/blog/protected/views/post/view.php` です。

以下のコードが、`PostController` で `view` 操作を実装する部分です:

~~~
[php]
public function actionView()
{
	$post=$this->loadModel();
	$this->render('view',array(
		'model'=>$post,
	));
}

private $_model;

public function loadModel()
{
	if($this->_model===null)
	{
		if(isset($_GET['id']))
		{
			if(Yii::app()->user->isGuest)
				$condition='status='.Post::STATUS_PUBLISHED
					.' OR status='.Post::STATUS_ARCHIVED;
			else
				$condition='';
			$this->_model=Post::model()->findByPk($_GET['id'], $condition);
		}
		if($this->_model===null)
			throw new CHttpException(404,'リクエストされたページは存在しません。');
	}
	return $this->_model;
}
~~~

主な変更点は `loadModel()` メソッドにあります。このメソッドで、GET パラメータの `id` に従って `Post` テーブルに問い合わせをします。記事が見つからない場合、あるいは、(ユーザがゲストであって) 記事が公開もアーカイブもされていない場合は、404 HTTP エラーを投げます。そうでなければ、記事オブジェクトが `actionView()` に返され、表示のためにビュースクリプトへと渡されていきます。

> Tip|ヒント: Yii は HTTP 例外 ([CHttpException] のインスタンス) を捕捉し、定義済みのテンプレートか、カスタマイズしたエラービューで表示します。`yiic` で生成されたスケルトンアプリケーションには既にカスタマイズしたエラービューが含まれています。ファイルは `/wwwroot/blog/protected/views/site/error.php` です。このファイルを修正すれば、エラー表示を更にカスタマイズできます。

`view` スクリプトの変更は、記事の表示に関するフォーマットとスタイルを調整することが中心になります。ここでは詳細には立ち入りません。興味のある方は `/wwwroot/blog/protected/views/post/view.php` を参照してください。


`index` 操作のカスタマイズ
-------------------------

`view` 操作と同様に、`index` 操作でも2ヶ所をカスタマイズします。`PostController` の `actionIndex()` メソッドと、ビューファイル `/wwwroot/blog/protected/views/post/index.php` です。主として、特定のタグに結び付いた記事の一覧表示に対するサポートを追加することが必要になります。

以下は、`PostController` の `actionIndex()` メソッドを修正したものです:

~~~
[php]
public function actionIndex()
{
	$criteria=new CDbCriteria(array(
		'condition'=>'status='.Post::STATUS_PUBLISHED,
		'order'=>'update_time DESC',
		'with'=>'commentCount',
	));
	if(isset($_GET['tag']))
		$criteria->addSearchCondition('tags',$_GET['tag']);

	$dataProvider=new CActiveDataProvider('Post', array(
		'pagination'=>array(
			'pageSize'=>5,
		),
		'criteria'=>$criteria,
	));

	$this->render('index',array(
		'dataProvider'=>$dataProvider,
	));
}
~~~

上の例では最初に、記事リストを取得するためのクエリー基準を作成します。この基準は、公開済みの記事だけを返し、並び順を更新時刻の降順にするという内容です。また、リスト表示するときは各記事のコメント数を表示したいので、`commentCount` を返す指示もあります。覚えているか分かりませんが、これは `Post::relations()` で宣言したリレーションです。

ユーザが特定のタグの記事を見たいという場合は、検索条件をクエリー基準に追加して、特定のタグだけを探すようにします。

このクエリー基準を使って、データプロバイダーを作ります。データプロバイダーは主に3つの仕事をこなします。まず、データが多いときにページネーション (ページ送り処理) をします。ここではページサイズを5にセットして、ページネーションをカスタマイズしています。次に、ユーザの要求に合わせてソートを行ないます。最後に、ページ送りとソートをしたデータを表示用のウィジェットやビューコードに供給します。

`actionIndex()` の修正が完了したら、`index` ビューを以下のように修正します。主な変更点は、表示する記事をユーザがタグで指定したときに、`h1` ヘッダーを追加することです。

~~~
[php]
<?php if(!empty($_GET['tag'])): ?>
<h1><i><?php echo CHtml::encode($_GET['tag']); ?></i> というタグを持つ記事</h1>
<?php endif; ?>

<?php $this->widget('zii.widgets.CListView', array(
	'dataProvider'=>$dataProvider,
	'itemView'=>'_view',
	'template'=>"{items}\n{pager}",
)); ?>
~~~

上の例で、記事リストの表示に [CListView] を使っていることに着目して下さい。このウィジェットは、個々の記事の詳細を表示するために部分的ビュー (partial view) を必要とします。ここで partial view として指定している `_view` は、`/wwwroot/blog/protected/views/post/_view.php` のことです。このビュースクリプトの中では、`$data` というローカル変数を使って、記事のインスタンスにアクセスできます。

<div class="revision">$Id$</div>