Bookmark and Share

Lee's 程序人生

HTML CSS Javascript XML AJAX ATLAS C# C++ 数据结构 软件工程 设计模式 asp.net Java 数字图象处理 Sql 数据库
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

YiiFrameworkBlog开发向导:完善评论模块

Posted on 2010-02-24 21:47  analyzer  阅读(423)  评论(0)    收藏  举报

像文章模块一样,我们需要完善评论模块的rules(), relations() 和 safeAttributes() 方法,另外我们还需要修改attributeLabels()方法,来为一些属性定义显示标签

修改rules()方法

我们首先修改由Yiic工具生成的验证规则,评论使用如下的验证规则

 
  1. public function rules()
  2. {
  3.     return array(
  4.         array('author,email,content''required'),
  5.         array('author,email,url','length','max'=>128),
  6.         array('email','email'),
  7.         array('url','url'),
  8.         array('verifyCode''captcha''on'=>'insert',
  9.             'allowEmpty'=>!Yii::app()->user->isGuest),
  10.     );
  11. }

 

在上面的代码中,我们指定用户名、邮箱、评论内容为必填项。用户名、邮箱、网址的最大长度不能超过128,email地址必须符合邮箱的规则,url必须有效的网址,verifyCode也必须通过验证。

上面提到的verifyCode属性,主要用于在用户添加新的评论时,保存其填写的验证码。因为他不存在于Comment表中,所以我们需要显式的声明它为公用变量。它用一个名字为captcha的验证器进行验证,可参看CCaptchaValidator类。然而验证码仅会出现在用户添加新的评论的时候(参看on选项),而且如果是已经通过验证的登录用户,则不会出现(参看allowEmpty选项)

修改safeAttributes()方法

我们修改safeAttributes()方法来指定那些属性可以被批量赋值

 
  1. public function safeAttributes()
  2. {
  3.     return array('author''email''url''content''verifyCode');
  4. }

 

这也同时指出评论表单应该由收集以下信息的字段组成:用户名、邮箱、网址、评论内容、验证码。

修改relations()方法

当我们开发最新评论模块时。我们需要一个带有相关文章信息的最新评论列表。因此我们需要修改relations()方法,来定义它和文章(post)的关系。

 
  1. public function relations()
  2. {
  3.     return array(
  4.         'post'=>array(self::BELONGS_TO, 'Post''postId',
  5.             'joinType'=>'INNER JOIN'),
  6.     );
  7. }

 

请注意我们的连接类型是INNER JOIN 这是因为一个评论必须从属于一篇文章。

修改attributeLabels() 方法

最后我们修改attributeLabels() 方法来定义属性的显示标签。该方法返回一个名值对数组。当我们调用CHtml::activeLabel()来显示一个属性的标签时,首先会检查该是否有一个定制的标签被声明,否则才按照一定的算法产生一个默认标签

 
  1. public function attributeLabels()
  2. {
  3.     return array(
  4.         'author'=>'Name',
  5.         'url'=>'Website',
  6.         'content'=>'Comment',
  7.         'verifyCode'=>'Verification Code',
  8.     );
  9. }

 

产生标签的算法是根据属性的名字。首先会按照大写拆分单词,然后修改每个单词的首字母为大写。例如verifyCode的默认标签就是Verify Code。

修改保存程序

因为我们想为每个文章保存评论数,当我们增加或者删除一条评论的时候我们需要修改当前文章的评论数,使其一致。我们通过重写 Comment模块的 afterSave()方法和afterDelete()方法来实现此功能。同时我们也重写了beforeValidate()方法,以便我们把Markdown格式转换为HTML格式,同时记录建立时间。

 
  1. protected function beforeValidate($on)
  2. {
  3.     $parser=new CMarkdownParser;
  4.     $this->contentDisplay=$parser->safeTransform($this->content);
  5.     if($this->isNewRecord)
  6.         $this->createTime=time();
  7.     return true;
  8. }
  9.  
  10. protected function afterSave()
  11. {
  12.     if($this->isNewRecord && $this->status==Comment::STATUS_APPROVED)
  13.         Post::model()->updateCounters(array('commentCount'=>1), "id={$this->postId}");
  14. }
  15.  
  16. protected function afterDelete()
  17. {
  18.     if($this->status==Comment::STATUS_APPROVED)
  19.         Post::model()->updateCounters(array('commentCount'=>-1), "id={$this->postId}");
  20. }

 

补充说明

或许你留意到了,上面程序中有个变量Comment::STATUS_APPROVED。你一定还记得发布文章的时候我们有三个状态:未发布、已发布、存档。这里评论也有两个两个状态,未审核和已审核。官方的向导里没有提到这块,还请留意。

有关状态的初始可以参看文章模块,也可以参看实例程序中的对应代码,现贴在下面仅供参看

 
  1. const STATUS_PENDING=0;
  2.     const STATUS_APPROVED=1;
  3.  
  4. /**
  5.      * @return array comment status names indexed by status IDs
  6.      */
  7.     public function getStatusOptions()
  8.     {
  9.         return array(
  10.             self::STATUS_PENDING=>'Pending',
  11.             self::STATUS_APPROVED=>'Approved',
  12.         );
  13.     }
  14.  
  15.     /**
  16.      * @return string the status display for the current comment
  17.      */
  18.     public function getStatusText()
  19.     {
  20.         $options=$this->statusOptions;
  21.         return isset($options[$this->status]) ? $options[$this->status] : "unknown ({$this->status})";
  22.     }
  23.