Управління записами =================== Під управлінням записами мається на увазі відображення їх списку у адміністративному розділі з можливістю переглядати записи з будь-яким статусом, редагувати та видаляти їх. Ця функціональність реалізується у діях `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/uk/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/uk/topics.security). Видалення записів ----------------- У таблиці данних `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), можна використовувати каскадне видалення коментарів у разі видалення запису. У цьому випадку немає необхідності видаляти коментарі у коді.