Комментарии.
На нашем сайте пользователи (как авторизированные так и неизвестные) должны иметь возможность комментировать каждую запись. Для этого мы создадим
контроллер Comments. По аналогии с контролером записей нужно воспользоваться утилитой yiic и командами model и crud.
После создания контроллера откройте его и подредактируйте правила доступа следующим образом. В разрешённые всем действия добавьте create. Действия
update, delete и admin удалите. Представим что всех их будет выполнять либо администратор ресурса, либо владелец блога.
Затем откройте отображение show, контроллера Records. После кода отображения записи поместите код формы, в которую посетитель будет вносить текст
комментария.
Код HTML:
<br />
<br />
<br />
<h3>Оставьте свой отзыв!</h3>
<form action="/comments/create/" method="post">
<input type="hidden" name="Comments[post_id]" value="<?=$model->id?>" />
<table width="100%">
<tr>
<td>Текст комментария:</td>
</tr>
<tr>
<td><textarea name="Comments[text]" class="long_field"></textarea></td>
</tr>
<tr>
<td><input type="submit" value="Сохранить" /></td>
</tr>
</table>
</form>
Далее нужно изменить сам контроллер. А именно - метод actionCreate. Изначально он выполняет сохранение тех данных которые приходят к нему из формы.
Но в форме у нас всего два поля - комментарий и номер записи. А в таблице должны быть заполнены ещё столько же - дата публикации и идентификатор автора.
Поэтому, прямо перед передачей POST-параметров в модель
PHP код:
$model->attributes = $_POST['Comments'];
мы создадим в POST-массиве две дополнительные ячейки. В одной будет номер автора (или 0 в случае неавторизированного гостя), а во второй - текущее
время в формате UNIX TIMESTAMP.
PHP код:
$_POST['Comments']['author_id'] = (Yii::app()->user->getId()) ? Yii::app()->user->getId() : 0;
$_POST['Comments']['pub_date'] = time();
Как всегда, изменим и код редиректа. Сейчас он перенаправляет пользователя на метод show, дабы тот увидел то что он опубликовал. Но нам нужно
показать посетителю не именно то что он оставил, а комментируемую запись и все сообщения комментаторов. Для этого мы перебросим его на метод show
контроллера create, поместив в ссылку номер комментируемой записи.
PHP код:
$this->redirect("/records/show/id/{$model->post_id}");
Следующим шагом нужно организовать отображение всех комментариев которые есть у записи. Сделать это можно двумя путями - в контроллере Records,
в методе actionShow, получить список отзывов о записи (например, описать для этого соответствующую функцию в модели Comments). А можно настроить ещё
одну связь в модели Records с моделью комментариев. Мы пойдём вторым путём и в массив, возвращаемый методом relations поместим вот такую ячейку.
PHP код:
'comments' => array(self::HAS_MANY,'Comments','post_id')
Так мы укажем приложению что у каждой записи имеется ( возможно ) множество комментариев, которые должны отбираться в модели Comments, по полю
post_id. Все они будут помещаться в итоговую модель, в соответствующую ячейку. Но в самих комментариях нам нужно отображать ещё и имя их автора.
Для этого применим связь которую уже объявляли при работе с записями - свяжем модель комментариев и модель пользователей по полю author_id.
PHP код:
'author' => array(self::BELONGS_TO,'Users','author_id'),
Осталось лишь отображение. Для этого в шаблон show поместите следующий код, прямо между формой отзыва и текстом записи.
Код HTML:
<br /><br /><br />
<h3>Комментарии:</h3>
<?foreach($model->comments as $comment):?>
<b>
<?if(isset($comment->author->login)):?>
<?=$comment->author->login?>
<?else:?>
Гость
<?endif;?>
(<?=date('d-m-Y',$comment->pub_date)?>)
</b><br />
<?=$comment->text?><br /><br />
<?endforeach;?>
Теперь у наших блогов есть ещё и комментарии.
Кэширование.
Ну и под конец коснёмся темы кэширования. Оно в Yii ( http://www.yiiframework.com/doc/guide/ru/caching.overview ) может быть реализовано с
помощью пяти компонентов - memCache, ACP, XCache, EAcceleratior и CDbCache. Для всех них создан один уникальный класс-оболочка - CCache
( http://www.yiiframework.com/doc/api/CCache#get-detail ). Через него можно работать со всеми пятью компонентами через один и тот же интерфейс.
Мы воспользуемся кэшированием с использованием базы данных ( CDbCache ). Для активизации компонента требуется открыть главный конфигурационный
файл, и в массив ячейки "components", добавить ячейку "cache" со следующим содержимым
PHP код:
'cache' => Array('class' => 'system.caching.CDbCache'),
Более ничего делать не нужно. Давайте применим кэширование к показу сообщений в блоге. Кэшировать мы будем данные получаемые из БД ( работа с данными
- http://www.yiiframework.com/doc/guide/ru/caching.data ). Задействовать нам нужно всего 3 метода - get, set и delete. Они принадлежат объекту
возвращаемому Yii::app()->cache. В качестве основного параметра им нужно передать специальный идентификатор ( обычное имя под которым кусок информации
будет записан, удалён или получен из кэша ). Из названий этих методов понятно что первый проверяет наличие определённых данных, второй эти данные
устанавливает, а третий - удаляет.
Откроем контроллер ответственный за записи в блогах и обратимся к методу actionShow. В нём мы будем кэшировать данные поступающие из базы. Изменим
код следующим образом. В начале мы получим номер запрашиваемой записи - он находится в параметре id. Далее, мы проверим - если кэш записи уже есть,
то достанем его и передадим в отображение. Если нет - вызовем метод loadRecords, сохраним в кэше его результат и передадим в отображение. Ничего сложного.
PHP код:
$id = (int) $_GET['id'];
if(Yii::app()->cache->get("show_{$id}") === false)
{
$model = $this->loadRecords();
Yii::app()->cache->set("show_{$id}",$model);
} else
$model = Yii::app()->cache->get("show_{$id}");
$this->render('show',array('model'=>$model));
Но ведь содержимое сообщения может изменяться. При этом старый кэш нужно будет удалять. В таких случаях следует описать вызов метода delete.
У нас они находятся в действиях редактирования и удаления. В "update" мы заменим код
PHP код:
if($model->save())
$this->redirect(array('show','id'=>$model->id));
на
PHP код:
if($model->save())
{
Yii::app()->cache->delete("show_{$model->id}");
$this->redirect(array('show','id'=>$model->id));
}
А в "delete", сразу перед редиректом мы вставим следующую строку:
PHP код:
Yii::app()->cache->delete("show_{$record->id}");
Всё, эта часть закончена.
Теперь рассмотрим работу с фрагментом страницы ( http://www.yiiframework.com/doc/guide/ru/caching.fragment ). Это ещё проще. Здесь задействуются
методы beginCache и endCache класса CController (то есть можно будет к нему обращаться в отображении через $this). Мы должны вызвать их в начале
и в конце того куска страницы который должен быть записан. При обращениях пользователей, если фрагмент уже находится в кэше он будет извлечён и
показан. Если же нет, то он выполнится и запишется.
Этим фрагментом будет код отвечающий за показ комментариев в отображении records/show. В качестве кэш-идентификатора у нас будет фраза
"comments_page_номер_страницы". Прямо перед заголовком "Комментарии" поместите следующий код:
PHP код:
<?if($this->beginCache("comments_page_{$model->id}")):?>
А после цикла foreach, и трёх переносов строк, вызов окончания кэширования.
PHP код:
<?$this->endCache("comments_page_{$model->id}");endif;?>
Ну и удаление кэша мы вызовем в контроллере Comments, в действии create, сразу перед редиректом.
PHP код:
Yii::app()->cache->delete("comments_page_{$_POST['Comments']['post_id']}");
Всё, теперь у нас кэшируются и записи, и комментарии. Как видите, всё очень легко.
Заключение.
На мой взгляд Yii, в отличие от многих других фреймворков, является инструментом с высоким порогом вхождения. Понять его основы, логику, принципы
и зависимости в начале довольно трудно. Так же мне кажется что утверждение разработчиков о том, что Yii можно использовать для любых приложений,
не верно. Всё-таки он больше подходит именно для веб-2.0-приложений ( как его позиционируют например на сайте журнала phpInside ). Если разобраться
то оказывается что по функционалу фреймворк очень хорош, и является одновременно мощным и простым.
Если в процессе чтения статьи у Вас что-то не получилось то Вы можете взять готовый код экспериментального приложения в архиве ready.zip. Удачи
Вам в Ваших проектах!