Отображение записей
===================

В нашем приложении запись может показываться как отдельно, так и среди других
записей. Первое реализуется действием `view`, второе — `index`. В данном разделе
мы изменим оба действия для достижения первоначальных требований.


Изменение действия `view`
-------------------------

Действие `view` реализовано в методе `actionView()` контроллера `PostController`.
Отдаваемый пользователю HTML генерируется из отображения `view`, находящегося
в файле `/wwwroot/blog/protected/views/post/view.php`.

Ниже приведён код действия `view` контроллера `PostController`:

~~~
[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()`. В нём мы получаем запись
из таблицы `Post`, используя параметр `id` из GET. Если запись не найдена,
не опубликована или находится в архиве, и при этом пользователь является
гостем — показываем ошибку 404. Иначе возвращаем объект записи методу `actionView()`,
который передаёт объект отображению.

> Tip|Подсказка: Yii перехватывает исключения HTTP (экземпляры класса
  [CHttpException]) и отображает их, используя либо предопределённые,
  либо свои шаблоны. Каркас, сгенерированный `yiic` уже содержит
  свой шаблон для ошибок в файле `/wwwroot/blog/protected/views/site/error.php`.
  При необходимости мы можем изменить этот файл.

Изменения в отображении `view` в основном затрагивают форматирование и стили
отображения записи, поэтому на нём мы останавливаться не будем.
Заинтересованные читатели могут обратиться к файлу
`/wwwroot/blog/protected/views/post/view.php`.


Изменение действия `index`
-------------------------

Как и в действии `view`, мы будем изменять действие `index` в двух местах:
метод `actionIndex()` контроллера `PostController` и отображение
`/wwwroot/blog/protected/views/post/index.php`. Требуется добавить поддержку
отображения записей с определённым тегом.

Ниже приведён изменённый метод `actionIndex()` контроллера `PostController`:

~~~
[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()`.

В том случае, когда пользователь хочет получить записи с определённым тегом,
мы добавляем в критерий условие поиска тега.

Используя критерий мы создаём провайдер данных, нужный для трёх целей. Во-первых,
он занимается постраничной разбивкой данных. Мы задаём количество результатов на
страницу равным 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].
Этот виджет использует отображение для построения каждой отдельной записи.
Мы указываем отображение `_view`, то есть файл
`/wwwroot/blog/protected/views/post/_view.php`, в котором мы можем
обращаться к записи через переменную `$data`.