一个表如何关联多个不同的表

一个表如:comment,包含字段idtype,idval,

idtype类型可以是blog、album等等,idval是blog或album 的主键id。

现在查询comment,如何才能同时查出blog或album的内容?

也就是说日志(blog)和相册(album)都有评论(comment),查询评论的时候同时查出日志和相册?

relations()函数应该怎么写?

目前 CActiveRecord 的 relations 设计应该只能分开写。




public function relations()

{

    return array(

        'belongs_to_blog'=>array(self::BELONGS_TO, 'Blog', 'idval', 'together' => false),

        'belongs_to_album'=>array(self::BELONGS_TO, 'Album', 'idval', 'together' => false),

    );

}



然后根据 idtype 手工决定是 $model->belongs_to_blog 还是 $model->belongs_to_album

希望 className 可以支持 expression 这样就可以




private static $relationClassNames = array(

    'blog' => 'Blog',

    'album' => 'Album',

);


public function getRelationClassName($name)

{

    if (array_key_exists($name, self::$relationClassNames))

        return self::$relationClassNames[$name];

    throw new CException("Error RelationClassName: '{$name}'");

}


public function relations()

{

    return array(

        'belongs_to'=>array(self::BELONGS_TO, '$model->getRelationClassName($model->idtype)', 'idval', 'together' => false),

    );

}



非常感谢Larry的回答。很详细。

按照


public function relations()

{

    return array(

        'belongs_to_blog'=>array(self::BELONGS_TO, 'Blog', 'idval', 'together' => false),

        'belongs_to_album'=>array(self::BELONGS_TO, 'Album', 'idval', 'together' => false),

    );

}

这个写法,查询的时候能够执行一次数据库查询就同时取出comment、blog、album的内容吗?不使用延迟载入(lazy)

‘together’ => false 就是 延迟载入

按照你的设计,肯定不能一次数据查询就完成。就是我设想的改进设计,也是分次查询的,findAll 需要查询一次,每次调用 relation attribute 的时候再查询一次。

也就是说,你查询 10 条数据,就要执行 11 个查询(1 + 查询的数据数)。

即使是优化的 SQL 查询,也需要 (1 + 查询的数据类型数)个查询。

也就是先 SELECT * FROM comment; 然后分别收集 blog 的 idval、album 的 idval,再分别 SELECT * FROM blog WHERE id in (xxx); 和 SELECT * FROM album WHERE id in (yyy);

我懂了,谢谢!!!

以这种设计,最优也需要(1 + 查询的数据类型数)。

我的需求是这样的:

blog表有message字段,表示内容

album有message字段,表示说明

我查询comment的时候,同时需要查询blog和album的message,终究不可避免(1+2)次数据库查询。

现把设计改为:

把blog.message字段和album.message字段,拿出来放在一个单独的表里,叫content表,有字段id(主键)和text,text表示前面的blog.message或album.message,然后在blog和album里添加一个字段idcontent指向content的主键ID,

那么我在comment里用idv来关联content的主键ID。

那么这样一次查询就可以取出comment、blog和album的message了。

这样的设计合理不?

那你为啥不把 message 直接放进 comment 表里面算了。具体的看任何一个 PHP 论坛的 thread 和 post 的表设计。