Управление записями =================== Под управлением записями подразумевается отображение их списка в административном разделе с возможностью просматривать записи с любым статусом, редактировать и удалять их. Эта функциональность реализуется в действиях `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), можно использовать каскадное > удаление комментариев в случае удаления записи. В этом случае нет необходимости > удалять комментарии в коде.