После того, как мы закончили с моделью 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')); ...... if(isset($_POST['previewPost']) && !$post->hasErrors()): ...отображаем предварительный просмотр модели $post... 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(),
который также выполняет валидацию данных. Если сохранение прошло успешно,
(не возникли ошибки валидации и данные сохранились в БД без ошибки) —
перенаправляем пользователя на страницу только что созданной записи.
Signup or Login in order to comment.