После того, как мы закончили с моделью Post, займёмся контроллером
PostController и его отображениями. В данном разделе мы настроим правила
доступа операций CRUD. Затем изменим код, отвечающий за создание(create) и
обновление(update). В завершение мы реализуем предварительный просмотр для
обеих операций.
Первое, что мы запланировали — настройка
прав доступа. Код,
сгенерированный при помощи yiic нам не подойдёт.
Необходимо изменить метод accessRules() в файле
/wwwroot/blog/protected/controllers/PostController.php следующим образом:
public function accessRules() { return array( array('allow', // все пользователи могут использовать действия 'list' и 'show' 'actions'=>array('list', 'show'), 'users'=>array('*'), ), array('allow', // аутентифицированные пользователи могут всё 'users'=>array('@'), ), array('deny', // все остальные не могут ничего 'users'=>array('*'), ), ); }
Описанные выше правила разрешают всем пользователям выполнять действия
list и show. Аутентифицированным — любые действия, включая admin.
Всем остальным пользователям запрещено всё. Стоит отметить, что правила
применяются в порядке их описания. Первое сработавшее правило определяет,
давать доступ или не давать. К примеру, если текущий пользователь является
владельцем системы и пытается зайти на страницу создания записи, будет применено
второе правило и доступ будет разрешён.
create и update ¶Операции create и update довольно похожи. В обоих случаях требуется
вывести HTML форму для сбора данных, вводимых пользователем. Также требуется
валидация и сохранение данных в БД. Главное отличие в том, что при update
форма будет заполняться данными о редактируемой записи. По этой причине yiic
генерирует вложенное отображение /wwwroot/blog/protected/views/post/_form.php,
которое включается как в отображение create, так и отображение update для
вывода HTML формы.
Для начала изменим файл _form.php таким образом, чтобы форма собирала только
нужные нам данные: title, content и status. Для первых двух атрибутов мы
используем текстовые поля. Для status — выпадающий список с всеми возможными
состояниями записи:
echo CHtml::activeDropDownList($post,'status',Post::model()->statusOptions);
Подсказка: Для получения состояний можно вместо
Post::model()->statusOptionsиспользоватьPost::model()->getStatusOptions(). Это возможно так какPostявляется компонентом, что даёт нам возможность использовать свойства, определённые как методы (геттеры).
Далее изменим класс Post таким образом, чтобы он автоматически выставлял
некоторые атрибуты (такие, как createTime и authorId) непосредственно перед
сохранением записи в БД. Перекроем метод beforeValidate():
protected function beforeValidate($on) { $parser=new CMarkdownParser; $this->contentDisplay=$parser->safeTransform($this->content); if($this->isNewRecord) { $this->createTime=$this->updateTime=time(); $this->authorId=Yii::app()->user->id; } else $this->updateTime=time(); return true; }
В данном методе мы используем CMarkdownParser для того, чтобы конвертировать
текст в формате Markdown в HTML
и сохранить результат в contentDisplay. Сделано это для того, чтобы
не конвертировать текст каждый раз при отображении записи. Если запись новая,
мы выставляем время создания(createTime) и автора(authorId). Иначе мы
выставляем время обновления(updateTime) как текущее время. Стоит отметить, что
данный метод вызывается автоматически при вызове методов модели validate()
или save().
Так как мы хотим сохранить теги записи в таблицу Tag, нам понадобится добавить
в класс Post метод, который будет вызываться автоматически после сохранения
записи:
protected function afterSave() { if(!$this->isNewRecord) $this->dbConnection->createCommand( 'DELETE FROM PostTag WHERE postId='.$this->id)->execute(); foreach($this->getTagArray() as $name) { if(($tag=Tag::model()->findByAttributes(array('name'=>$name)))===null) { $tag=new Tag(array('name'=>$name)); $tag->save(); } $this->dbConnection->createCommand( "INSERT INTO PostTag (postId, tagId) VALUES ({$this->id},{$tag->id})")->execute(); } } public function getTagArray() { // break tag string into a set of tags return array_unique( preg_split('/\s*,\s*/',trim($this->tags),-1,PREG_SPLIT_NO_EMPTY) ); }
Сначала удаляем все записи, связанные с данной из таблицы PostTag. Затем
вставляем новые теги в таблицу Tag и добавляем соответствующую запись в PostTag.
Логика в данном случае немного сложная, поэтому вместо использования
ActiveRecord, мы пишем выражения SQL и выполняем
их напрямую через соединение с БД.
Подсказка: Хорошим тоном является отделение бизнес-логики, такой как
beforeValidate()иafterSave(), описанные выше и размещение её в моделях, а не в контроллерах.
Кроме изменений, описанных выше, нам необходимо добавить возможность предварительного просмотра, которая позволит нам оценить запись до её сохранения в БД.
Для того, чтобы добавить кнопку «предварительный просмотр» и само отображение
записи, изменим представление _form.php. Просмотр отображается только при
нажатии кнопки и если не произошло ошибок валидации.
echo CHtml::submitButton('Предварительный просмотр',array('name'=>'previewPost')); ...... <?php if(isset($_POST['previewPost']) && !$post->hasErrors()): ...отображаем предварительный просмотр модели $post... <?php endif;
Добавим в методы actionCreate() и actionUpdate() контроллера PostController обработку
запроса на предварительный просмотр. Ниже приведён код actionCreate(), который
очень похож на то, что необходимо сделать и в actionUpdate():
public function actionCreate() { $post=new Post; if(isset($_POST['Post'])) { $post->attributes=$_POST['Post']; if(isset($_POST['previewPost'])) $post->validate(); else if(isset($_POST['submitPost']) && $post->save()) $this->redirect(array('show','id'=>$post->id)); } $this->render('create',array('post'=>$post)); }
При нажатии на кнопку «предварительный просмотр» мы вызываем $post->validate()
для выполнения валидации введённых данных. Если же нажали на кнопку
«сохранить»(submit) — пробуем сохранить запись при помощи $post->save(),
который также выполняет валидацию данных. Если сохранение прошло успешно,
(не возникли ошибки валидации и данные сохранились в БД без ошибки) —
перенаправляем пользователя на страницу только что созданной записи.
Be the first person to leave a comment
Please login to leave your comment.