天天看点

YiiFrameworkBlog开发向导:定制文章模块

由yiic工具生成的文章模块主要有以下三个地方需要完善:

  • rules()方法:模块属性的验证规则。也就是表中数据的验证规则
  • relations()方法 :各个模块的相互关系,也就是各个表的相互关系。
  • safeAttributes()方法:允许批量赋值的属性。

模块有许多和数据表中字段对应的属性。属性可以显式的通过类的变量进行声明,也可以隐式的不采用任何声明。也就是可以把属性都作为变量声明出来,也可以不进行任何声明。

修改rules()方法

首先我们要在数据存到数据表之前,验证用户输入的数据是否合法。比如说状态属性。我们只希望它是0,1或者2.来表示草稿、发布和归档。而不要是其他值。yiic 工具虽然也会自动的生成一些规则。但是都是根据数据表中字段的信息产生的,有些或许并不适用。

根据需求分析我们把验证规则做如下修改:

  1. public function rules()
  2. {
  3.     return array(
  4.         array('title, content, status', 'required'),
  5.         array('title', 'length', 'max'=>128),
  6.         array('status', 'in', 'range'=>array(0, 1, 2)),
  7.         array('tags', 'match', 'pattern'=>'/^[\w\s,]+$/',
  8.             'message'=>'Tags can only contain word characters.'),
  9.     );
  10. }

我们把标题、正文和状态三个字段修改为必须填写。标题的长度最大是128.状态只能是0、1、2.标签只能用字母和逗号。其他的属性不要验证,因为那些不是从用户提交的表单读取的.

修改完之后我们可以尝试建立帖子,来测试规则是否生效。需要主意的是上面标签的规则不适用于中文。

验证规则会在我们调用模块实例的validate() 或save()方法时被调用。

修改safeAttributes()方法

我们修改safeAttributes()方法来指定可以批量赋值的属性。我们以前把用户输入批量赋值给实例变量可以这么写:

  1. $post->attributes=$_POST['Post'];

如果不用上述方法的话我们需要写上一大堆这样的代码

  1. $post->title=$_POST['Post']['title'];
  2. $post->content=$_POST['Post']['content'];
  3. ......

批量赋值的方法相对简单,但是它存在一个潜在的危险,恶意用户可以回提交一些你不希望被修改或者只让管理员来修改的字段的值。比如说id字段一般是不允许修改的。

为了避免这种危险,我们如下修改safeAttributes() 方法。来指定只有标题、正为、状态和标签是允许被批量赋值的。

  1. public function safeAttributes()
  2.     return array('title', 'content', 'status', 'tags');

一个简单的方法是,可以通过用户输入表单来判断哪些字段应该被允许批量赋值。模块属性中那些在表单中向用户展示,用来收集用户输入的属性应该被允许批量赋值,通常情况下他们也需要被验证规则进行验证。

修改relations()方法

最后我们来修改relations()方法来定义其它对象和post的关系。通过定义对象之间的关系,我们能生成强有力的Relational ActiveRecord (RAR)作为相关对象的接口。而不需要在编写复杂的SQL JOIN语句

  1. public function relations()
  2.         'author'=>array(self::BELONGS_TO, 'User', 'authorId'),
  3.         'comments'=>array(self::HAS_MANY, 'Comment', 'postId',
  4.             'order'=>'??.createTime'),
  5.         'tagFilter'=>array(self::MANY_MANY, 'Tag', 'PostTag(postId, tagId)',
  6.             'together'=>true,
  7.             'joinType'=>'INNER JOIN',
  8.             'condition'=>'??.name=:tag'),

以上关系表明

  • 一个帖子属于BELONGS_TO)一个用户。根据authorId字段和用户的User类进行关联
  • 一个帖子有多个(HAS_MANY)评论。根据postId字段和评论的Comment类进行关联,评论按照建立的时间进行排序。
  • 帖子和标签(Tag)是多对多(MANY_MANY)的关系,通过PostTag(postId, tagId)进行关联。表示自身的主键对应PostTag的postId PostTag的tagId对应Tag的主键

根据以上定义,我们可以很容易的读取一篇文章的用户和评论信息。如

  1. $author=$post->author;
  2. echo $author->username;
  3. $comments=$post->comments;
  4. foreach($comments as $comment)
  5.     echo $comment->content;

用文字来表示状态

因为数据库中保存的文章的状态是个整数。我们需要提供文字的描述,这样看起来便会直观一些。所以做如下修改

  1. class Post extends CActiveRecord
  2.     const STATUS_DRAFT=0;
  3.     const STATUS_PUBLISHED=1;
  4.     const STATUS_ARCHIVED=2;
  5.     ......
  6.     public function getStatusOptions()
  7.     {
  8.         return array(
  9.             self::STATUS_DRAFT=>'Draft',
  10.             self::STATUS_PUBLISHED=>'Published',
  11.             self::STATUS_ARCHIVED=>'Archived',
  12.         );
  13.     }
  14.     public function getStatusText()
  15.         $options=$this->statusOptions;
  16.         return isset($options[$this->status]) ? $options[$this->status]
  17.             : "unknown ({$this->status})";

继续阅读