我有一个同一类的Active Record对象数组。 该对象具有已定义的关系。 在“父”对象初始化之后,有没有办法以“批量”方式读取相关对象?
实施例 我已经定义了AR类发布,用户,评论 * 发布 *将所有者(BELONGS_TO)与用户类关联,并将评论(HAS_MANY)与评论
我有一个数组 $ posts 类发布的对象。 由于不同的原因,无法从
开始初始化 $ posts'with' => array('owner', 'comments')
如果我这样做:
foreach ($posts as $post) {
var_dump($post->owner);
var_dump($post->comments);
}
对于每个 $ post ,可以查询所有者的查询以及重新评论的查询。 这可能导致大量的查询和慢速执行。 更好的方法是一步读取一种类型的所有相关对象。
对于一个对象数组,是否存在类似于某种关系的所有相关对象?:
Post::readRelatedObject($posts, 'owner');
Post::readRelatedObject($posts, 'comments');
出于以下几个原因,我需要这个方法:
yii是否包含这样的内容?还是一个可以提供帮助的插件?
谢谢
答案 0 :(得分:2)
如果您正在尝试针对这样的大型结果集进行优化,那么您几乎总是更喜欢自己滚动。 Yii开发人员even recommend没有使用activerecord来处理这种复杂情况(非常不同的加载顺序)。
首先,我建议根据您检索的所有帖子的ID建立自己的CDBCriteria
。如果你在Posts
模型中执行此操作,它也可以很好地(显然不完美)与为关系定义的标准绑定。
static public function loadComments(array $ids)
{
$crit = Comment::model()->dbCriteria;
$crit->addInCondition('post_id', .....
.....
return Comment::model()->findAll($crit);
}
这会给你所有关于这组ID的评论,你甚至可以做一些额外的处理,用它们所属的帖子ID来索引它们。
在你的评论中,你说这100个帖子,每个200条评论可能意味着加载2000(实际上是20 000)。但是如果你在一个页面上加载了很多帖子+评论,你就会在错误的地方进行优化。
在我看来担心数据库查询大小之前,您需要执行一些操作:
在需要之前不要加载评论,只需单击按钮,滚动到该帖子的标题,或者只是逐步向下翻页直到完成。这样,服务器一次只查找一个帖子的评论,用户甚至可能不希望看到第99号帖子的评论。
每页不要加载100个帖子,除非它们是非常小的帖子(在这种情况下,有什么担心)。逐步滚动将有助于,甚至pagination
过滤您的搜索结果只会显示相关内容,很可能不会有100个用户想看到的帖子,如果有200条评论,有多少用户会阅读超过10条?
如果你实现其中的一个,我认为结果集大小的问题将会消失。
如果确实确实需要担心20 000行,那么ActiveRecord实例化应首先在您的雷达上。在任何正常设置中都不用担心20 000行,但即使在更高规格的系统上,也肯定会有20 000个活动记录对象。如果你正在处理非常大和/或复杂的数据集,你应该使用DAO。
答案 1 :(得分:0)
我不知道可以做到这一点的扩展。也许你可以创建一个yii应该知道有关数据的一切来解决这个任务。
假设comment
有一个post_id
链接到id
表格中的post
。
有几个选项可以加载帖子的相关评论。
选项1 :使用ID查询所需的评论。某些DBMS限制了SQL查询的长度,因此您可能必须小心并且不要在IN子句中放置许多ID。也许这必须分成多个查询。
$posts
并将帖子id
存储在列表中。 SELECT * FROM comments WHERE post_id IN ([the IDs from the list])
。$posts
。选项2 :要修复可能的IN子句限制,请改用JOIN。
SELECT * FROM comments JOIN [the SELECT query for the posts]
之类的SQL查询。 选项3 (我的首选):根据您的使用情况,最简单的方法是重新加载包含评论和作者的所有帖子(通过在{{1}上定义with
在criteria
模型中)。
posts
:with
答案 2 :(得分:0)
如果您主要关注的是避免延迟加载,并希望检索所有帖子及其相关的所有者和评论记录。
这对你有用。
$criteria = new CDbCriteria();
$criteria->with = array('comments','owner');
$result = $Post->together()->findAll($criteria);
参考: http://www.yiiframework.com/doc/api/1.1/CActiveRecord#together-detail http://www.yiiframework.com/doc/api/1.1/CDbCriteria#with-detail
希望这可以回答您的问题。