Управление записями
===================
Под управлением записями подразумевается отображение их списка в административном
разделе с возможностью просматривать записи с любым статусом, редактировать и
удалять их. Эта функциональность реализуется в действиях `admin` и `delete`
соответственно. Код, сгенерированный при помощи `Gii` почти не нуждается в
изменениях. Ниже мы объясним, как реализованы эти действия.
Отображение записей в виде таблицы
----------------------------------
Действие `admin` выводит записи со всеми статусами в виде таблицы,
разбитой на несколько страниц и поддерживающей сортировку по нескольким колонкам.
Далее приведён метод `actionAdmin()` контроллера `PostController`:
~~~
[php]
public function actionAdmin()
{
$model=new Post('search');
if(isset($_GET['Post']))
$model->attributes=$_GET['Post'];
$this->render('admin',array(
'model'=>$model,
));
}
~~~
Данный код полностью сгенерирован `Gii`. Сначала создаётся модель `Post` со сценарием
`search` [scenario](/doc/guide/ru/form.model), которую мы будем использовать для
сбора критериев поиска, указанных пользователем. Далее мы присваиваем
данные, введённые пользователем, модели. И, наконец, мы выводим отображение
`admin`, используя модель.
Ниже приведён код отображения `admin`:
~~~
[php]
breadcrumbs=array(
'Manage Posts',
);
?>
Manage Posts
widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
array(
'name'=>'create_time',
'type'=>'datetime',
'filter'=>false,
),
array(
'class'=>'CButtonColumn',
),
),
)); ?>
~~~
Для вывода записей мы используем компонент [CGridView], который
разбивает данные на страницы и позволяет их сортировать по столбцам.
Наше изменение касается, главным образом, отображения каждого столбца.
К примеру, для столбца `title` мы указываем, что он должен содержать
ссылку на просмотр записи. Выражение `$data->url` возвращает значение
свойства `url`, которое мы определяем в классе `Post`.
> Tip|Подсказка: При выводе текста мы используем [CHtml::encode()] для
кодирования сущностей HTML. Это позволяет избежать атак через [межсайтовый
скриптинг](/doc/guide/ru/topics.security).
Удаление записей
----------------
В data grid `admin` в каждой строке есть кнопка «Удалить», удаляющая соответствующую
запись. Действие `delete` выглядит следующим образом:
~~~
[php]
public function actionDelete()
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$this->loadModel()->delete();
if(!isset($_GET['ajax']))
$this->redirect(array('index'));
}
else
throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}
~~~
Приведённый выше код полностью сгенерирован `Gii`. Остановимся подробнее на
проверке `$_GET['ajax']`. В виджете [CGridView] сортировка, постраничная
разбивка и удаление по умолчанию реализованы с использованием AJAX. То есть при
выполнении перечисленных действий страница перезагружаться не будет.
Виджет может работать и без AJAX (если свойство `ajaxUpdate` выставлено в
`false` или отключен JavaScript). В действии `delete` при AJAX запросе перенаправление
производиться не должно.
Удаление записи должно вызывать удаление всех комментариев к ней. Вдобавок,
мы должны обновить теги в таблице `tbl_tag`. Обе задачи могут быть выполнены
в методе `afterDelete` модели `Post`:
~~~
[php]
protected function afterDelete()
{
parent::afterDelete();
Comment::model()->deleteAll('post_id='.$this->id);
Tag::model()->updateFrequency($this->tags, '');
}
~~~
Код, приведённый выше не сложен: сначала удаляются все комментарии, чей
`post_id` равен ID удаляемой записи. Далее обновляется таблица `tbl_tag`.
> Tip|Подсказка: Мы удаляем комментарии удаляемой записи в коде, так как SQLite
> не поддерживает ограничения по внешнему ключу. В СУБД, которые данное ограничение
> поддерживают (например, MySQL или PostgreSQL), можно использовать каскадное
> удаление комментариев в случае удаления записи. В этом случае нет необходимости
> удалять комментарии в коде.