我们已经修改好了post model。还需要调整一下PostController控制器的视图(view)和动作(action)。在本节中我们首先完善controller中进行CRUD操作的权限。然后完善添加和更新操作。最后实现文章的预览。

操作权限

第一件事情便是完善访问权限,因为用Yiic工具生成的并不是我们需要的。我们如下修改/wwwroot/blog/protected/controllers/PostController.php文件中的accessRules()方法。

 
  1. public function accessRules()
  2. {
  3.     return array(
  4.         array('allow',  // allow all users to perform 'list' and 'show' actions
  5.             'actions'=>array('list''show'),
  6.             'users'=>array('*'),
  7.         ),
  8.         array('allow'// allow authenticated users to perform any action
  9.             'users'=>array('@'),
  10.         ),
  11.         array('deny',  // deny all users
  12.             'users'=>array('*'),
  13.         ),
  14.     );
  15. }

 

以上规则说明用户(包括访客的所有用户)可以访问list和show方法,验证用户(已登录的用户)可以访问所有方法。包括admin方法。其他情况一律禁止。注意是的是验证时会按照在这里的顺序进行。第一条规则不符合时会进行第二条的验证,如果还不符合则再往下验证,以此类推。

添加和更新操作的完善

添加和修改非常接近,他们都需要form表单,输入都需要验证,都需要保存。主要的不同在于更新操作需要预填充form表单,也就是根据原有的数据显示默认值。Yiic工具生成了/wwwroot/blog/protected/views/post/_form.php文件来提供添加或者更新时所需的HTML form。

我们首先修改_form.php。只保留我们需要的部分:标题、正文、状态和标签。其他的内容删除。其中状态提供下拉菜单让用户选择.修改原来的

 
  1. <?php echo CHtml::activeTextField($post,'status'); ?>

 

 
  1. <?php echo CHtml::activeDropDownList($post,'status',Post::model()->statusOptions); ?>

 

在上面的修改中,我们也可以使用 Post::model()->getStatusOptions()代替Post::model()->statusOptions来获取可用的状态选项。我们之所以可以使用后者是因为post组件允许我们以属性的方式读取getter方法。

然后修改post类,已让系统在数据保存到数据库前,自动的填充某些属性(如:创建时间、用户id)。我们重写了 beforeValidate()方法:

 
  1. protected function beforeValidate($on)
  2. {
  3.     $parser=new CMarkdownParser;
  4.     $this->contentDisplay=$parser->safeTransform($this->content);
  5.     if($this->isNewRecord)
  6.     {
  7.         $this->createTime=$this->updateTime=time();
  8.         $this->authorId=Yii::app()->user->id;
  9.     }
  10.     else
  11.         $this->updateTime=time();
  12.     return true;
  13. }

 

在这个方法中我们用CMarkdownParser把content从Markdown格式转为HTML格式。并把结果保存到contentDisplay中。避免了我们显示一篇文章时重复的格式转换。如果文章是新增的则添加作者和创建时间,否则修改更新时间。当执行validate()或者save() 时,该方法会被自动调用。

因为我们希望把文章的标签保存到Tag表。我们修改Post类,使其在保存文章后自动调用。

 
  1. protected function afterSave()
  2. {
  3.     if(!$this->isNewRecord)
  4.         $this->dbConnection->createCommand(
  5.             'DELETE FROM PostTag WHERE postId='.$this->id)->execute();
  6.  
  7.     foreach($this->getTagArray() as $name)
  8.     {
  9.         if(($tag=Tag::model()->findByAttributes(array('name'=>$name)))===null)
  10.         {
  11.             $tag=new Tag(array('name'=>$name));
  12.             $tag->save();
  13.         }
  14.         $this->dbConnection->createCommand(
  15.             "INSERT INTO PostTag (postId, tagId) VALUES ({$this->id},{$tag->id})")->execute();
  16.     }
  17. }
  18.  
  19. public function getTagArray()
  20. {
  21.     // break tag string into a set of tags
  22.     return array_unique(
  23.         preg_split('/\s*,\s*/',trim($this->tags),-1,PREG_SPLIT_NO_EMPTY)
  24.     );
  25. }

 

在上面的代码中我们先清除了PostTag表中相关的记录。然后将新的tag记录插入,如果不存在则建立之。

实现预览

除了以上修改之外我们还希望实现预览功能,让用户在保存前可以进行预览。首先我们修改_form.php 文件添加预览按钮和预览的展示。预览只有当用户点击了预览按钮并且所提交的内容没有错误的时候显示。

 
  1. <?php if(isset($_POST['previewPost']) && !$post->hasErrors()): ?>
  2. <h3>Preview</h3>
  3. <div class="post">
  4.   <div class="title"><?php echo CHtml::encode($post->title); ?></div>
  5.   <div class="author">posted by <?php echo Yii::app()->user->name . ' on ' . date('F j, Y',$post->createTime); ?></div>
  6.   <div class="content"><?php echo $post->contentDisplay; ?></div>
  7. </div><!-- post preview -->
  8. <?php endif; ?>

 

以上代码可以补加到_form.php,用来实现预览按钮,和预览的显示。注意补加的时候预览按钮一定要放在form中,否则不能提交表单的。也就是<?php if(isset($_POST['previewPost']) && !$post->hasErrors()): ?>一句,要放在_form.php中的<!-- yiiForm -->之前。

然后我们修改controller中的actionCreate() 和 actionUpdate() 方法来响应预览。下面显示的是actionCreate().actionUpdate()中与此相同。

 
  1. public function actionCreate()
  2. {
  3.     $post=new Post;
  4.     if(isset($_POST['Post']))
  5.     {
  6.         $post->attributes=$_POST['Post'];
  7.         if(isset($_POST['previewPost']))
  8.             $post->validate();
  9.         else if(isset($_POST['submitPost']) && $post->save())
  10.             $this->redirect(array('show','id'=>$post->id));
  11.     }
  12.     $this->render('create',array('post'=>$post));
  13. }

 

如果点击了预览按钮我们调用 $post->validate()来验证输入是否合法。如果点击的保存按钮,我们调用$post->save()进行保存时也会自动的进行验证。如果保存成功我们跳转地址到一个新的建立文章的页面