一个表如:comment,包含字段idtype,idval,
idtype类型可以是blog、album等等,idval是blog或album 的主键id。
现在查询comment,如何才能同时查出blog或album的内容?
也就是说日志(blog)和相册(album)都有评论(comment),查询评论的时候同时查出日志和相册?
relations()函数应该怎么写?
一个表如: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 的表设计。