Показать сообщение отдельно

  #5  
Старый 10.07.2009, 10:01
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

Комментарии.
На нашем сайте пользователи (как авторизированные так и неизвестные) должны иметь возможность комментировать каждую запись. Для этого мы создадим
контроллер 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. Удачи
Вам в Ваших проектах!