您好,UncleToo欢迎您!  为了更好的浏览本站,请使用高版本浏览器
RSS  Tag     设为首页 | 加入收藏
 您所在的位置:首页 > PHP框架 > Yii Framework

Yii Framework 自定义资讯模型

作者:  来源:YIIBASE  日期:2013-11-18 14:51:46
收藏  评论:( 0 )  阅读:374

yiic 工具生成的 Post 资讯模型类主要需要做如下两处修改:

  1. rules() 方法:指定对模型属性的验证规则;

  2. relations() 方法:指定关联的对象;

信息:模型 包含了一系列属性,每个属性关联到数据表中相应的列。属性可以在类成员变量中显式定义,也可以隐式定义,不需要事先声明。

自定义 rules() 方法

我们先来指定验证规则,它可以确保用户输入的信息在保存到数据库之前是正确的。例如, Post 的 status 属性应该是 1, 2 或 3 中的任一数字。 yiic 工具其实也为每个模型生成了验证规则,但是这些规则是基于数据表的列信息的,可能并不是非常恰当。

基于需求分析,我们把 rules() 做如下修改:

public function rules()
{
    return array(
        array('title, content, status', 'required'),
        array('title', 'length', 'max'=>128),
        array('status', 'in', 'range'=>array(1,2,3)),
        array('tags', 'match', 'pattern'=>'/^[\w\s,]+$/',
            'message'=>'Tags can only contain word characters.'),
        array('tags', 'normalizeTags'),
                                                 
        array('title, status', 'safe', 'on'=>'search'),
    );
}

在上面的代码中,我们指定了 title, content 和 status 属性是必填项;title 的长度不能超过 128;status 属性值应该是 1 (草稿), 2 (已发布) 或 3 (已存档);tags 属性应只允许使用单词字母和逗号。另外,我们使用 normalizeTags 来规范化用户输入的Tag,使Tag是唯一的且整齐地通过逗号分隔。最后的规则会被搜索功能用到,这个我们后面再讲。

像 required, length, in 和 match 这几个验证器(validator)是Yii提供的内置验证器。normalizeTags 验证器是一个基于方法的验证器,我们需要在 Post 类中定义它。关于如何设置验证规则的更多信息,请参考 指南。

public function normalizeTags($attribute,$params)
{
    $this->tags=Tag::array2string(array_unique(Tag::string2array($this->tags)));
}

其中的 array2string 和 string2array 是在 Tag 模型类中定义的新方法。详情请参考 /wwwroot/yii/demos/cms/protected/models/Tag.php 文件。

rules() 方法中定义的规则会在模型实例调用其 validate() 或 save() 方法时逐一执行。

注意:请务必记住 rules() 中出现的属性必须是那些通过用户输入的属性。其他的属性,如 Post 模型中的 id 和 create_time ,是通过我们的代码或数据库设定的,不应该出现在 rules() 中。详情请参考 属性的安全赋值(Securing Attribute Assignments).

作出这些修改之后,我们可以再次访问资讯创建页检查新的验证规则是否已生效。

自定义 relations() 方法

最后我们来自定义 relations() 方法,以指定与资讯相关的对象。通过在 relations() 中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问资讯的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。

我们自定义 relations() 方法如下:

public function relations()
{
    return array(
        'author' => array(self::BELONGS_TO, 'User', 'author_id'),
        'comments' => array(self::HAS_MANY, 'Comment', 'post_id',
            'condition'=>'comments.status='.Comment::STATUS_APPROVED,
            'order'=>'comments.create_time DESC'),
        'commentCount' => array(self::STAT, 'Comment', 'post_id',
            'condition'=>'status='.Comment::STATUS_APPROVED),
    );
}

我们还在 Comment 模型类中定义了两个在上面的方法中用到的常量。

class Comment extends CActiveRecord
{
    const STATUS_PENDING=1;
    const STATUS_APPROVED=2;
    ......
}

relations() 中声明的关系表明:
  1. 一篇资讯属于一个作者,它的类是 User ,它们的关系建立在资讯的 author_id 属性值之上;

  2. 一篇资讯有多个评论,它们的类是 Comment ,它们的关系建立在评论的 post_id 属性值之上。这些评论应该按它们的创建时间排列,且评论必须已通过审核;

  3. commentCount 关系有一点特别,它返回一个关于资讯有多少条评论的一个聚合结果。

通过以上的关系声明,我们现在可以按下面的方式很容易的访问资讯的作者和评论信息。

$author=$post->author;
echo $author->username;
                                
$comments=$post->comments;
foreach($comments as $comment)
    echo $comment->content;

关于如何声明和使用关系的更多详情,请参考手册或指南.

添加 url 属性

资讯是一份可以通过一个唯一的URL访问的内容。我们可以在 Post 模型中添加一个 url 属性,这样同样的创建URL的代码就可以被复用,而不是在代码中到处调用 CWebApplication::createUrl 。 稍后讲解怎样美化 URL 的时候,我们将看到添加这个属性给我们带来了超拽的便利。

要添加 url 属性,我们可以按如下方式给 Post 类添加一个 getter 方法:

class Post extends CActiveRecord
{
    public function getUrl()
    {
        return Yii::app()->createUrl('post/view', array(
            'id'=>$this->id,
            'title'=>$this->title,
        ));
    }
}

注意我们除了使用资讯的ID之外,还添加了资讯的标题作为URL中的一个 GET 参数。这主要是为了搜索引擎优化 (SEO) 的目的,在 美化 URL 中将会讲述。

由于 CComponent 是 Post 的最顶级父类,添加 getUrl() 这个 getter 方法使我们可以使用类似 $post->url 这样的表达式。当我们访问 $post->url 时,getter 方法将会被执行,它的返回结果会成为此表达式的值。关于这种组件的更多详情,请参考 指南。

以文本方式显示状态

由于资讯的状态在数据库中是以一个整型数字存储的,我们需要提供一个文本话的表现形式,这样在它显示给最终用户时会更加直观。在一个大的系统中,类似的需求是很常见的。

作为一个总体的解决方案,我们使用 tbl_lookup 表存储数字值和被用于其他数据对象的文本值的映射。为了更简单的访问表中的文本数据,我们按如下方式修改 Lookup 模型类:

class Lookup extends CActiveRecord
{
    private static $_items=array();
                        
    public static function items($type)
    {
        if(!isset(self::$_items[$type]))
            self::loadItems($type);
        return self::$_items[$type];
    }
                        
    public static function item($type,$code)
    {
        if(!isset(self::$_items[$type]))
            self::loadItems($type);
        return isset(self::$_items[$type][$code]) ? self::$_items[$type][$code] : false;
    }
                        
    private static function loadItems($type)
    {
        self::$_items[$type]=array();
        $models=self::model()->findAll(array(
            'condition'=>'type=:type',
            'params'=>array(':type'=>$type),
            'order'=>'position',
        ));
        foreach($models as $model)
            self::$_items[$type][$model->code]=$model->name;
    }
}

我们的新代码主要提供了两个静态方法: Lookup::items() 和 Lookup::item()。前者返回一个属于指定的数据类型的字符串列表,后者按指定的数据类型和数据值返回一个具体的字符串。

我们的资讯数据库已经预置了两个查询类别: PostStatus 和 CommentStatus。前者代表可用的日志状态,后者代表评论状态。

为了使我们的代码更加易读,我们还定义了一系列常量,用于表示整数型状态值。我们应该在涉及到相应的状态值时在代码中使用这些常量。

class Post extends CActiveRecord
{
    const STATUS_DRAFT=1;
    const STATUS_PUBLISHED=2;
    const STATUS_ARCHIVED=3;
    ......
}

这样,我们可以通过调用 Lookup::items('PostStatus') 来获取可用的资讯状态列表(按相应的整数值索引的文本字符串),通过调用 Lookup::item('PostStatus', Post::STATUS_PUBLISHED) 来获取发布状态的文本表现形式。


原文地址:http://www.yiibase.com/cookbook/yii/model.html



除非特别声明,本站所有PHP教程及其他教程/文章均为原创、翻译或网友投稿,版权均归UncleToo中文网所有, 转载请注明作者及出处。
原文网址:http://www.uncletoo.com/html/yii/670.html
读完这篇文章后,你是否有所收获? 分享是一种生活的信念!
  • 0
  • 0
我来说两句
更多>>网友评论