【发布时间】:2015-11-26 15:00:57
【问题描述】:
我有 Posts 和 Tags 模型,与“属于多个”关联。
所以在我的数据库中,我有 posts 和 tags 表和一个带有 post_id 和 tag_id 字段的 posts_tags 表。 tags 表有 post_count 字段,显示属于该标签的帖子数。
当我收到一个帖子时,我也会得到与之相关的标签。
$this->Posts->find()
->contain(['Tags'])
->where(['Posts.id' => $id])
->first());
现在,对于每个标签,我想获得一个具有该标签的帖子,不包括初始帖子,排序创建日期(created 字段)。
重要的是,每个标签都会获得一个帖子,而不是已经获得的帖子。
我可以使用foreach 并为每个标签获取一个包含它的帖子,方法是排除初始帖子的 ID 和已经获得的 ID。
我想知道我是否可以用一个查询来做到这一点,并有一个可以使用的示例。
谢谢。
编辑
临时解决方案,对每个标签使用查询
首先,我得到主帖:
$post = $this->Posts->find()
->contain(['Tags'])
->where(['Posts.id' => $id])
->first();
在这种情况下,帖子是通过其 ID 恢复的,但您可以采取不同的做法。您也可以使用缓存。
重要的事情是$post 变量。
现在(使用缓存是个好主意……):
//Tries to gets related posts from cache
$related = Cache::read($cache = sprintf('related_posts_for_%s', $post->id), 'posts');
if(empty($related)) {
$tags = $post->tags;
//Re-orders tags, using the "post_count" field, then based on the popularity of tags
usort($tags, function($a, $b) { return $b['post_count'] - $a['post_count']; });
//Gets only the first 5 tags
$tags = array_slice($tags, 0 , 5);
//This array will be contain the ID to be excluded
$exclude = [$post->id];
//Gets a related post for each tag
//Reveres the tags order, because the tags less popular have less chance to find a related post
foreach(array_reverse($tags) as $tag) {
$post = $this->Posts->find('active')
->select(['id', 'title', 'slug'])
->matching('Tags', function($q) use($tag) {
return $q->where(['Tags.id' => $tag->id]);
})
->where(['Posts.id NOT IN' => $exclude])
->first();
//Adds the post to the related posts and its ID to the IDs to be excluded for the next query
if(!empty($post)) {
$related[] = $post;
$exclude[] = $post->id;
}
}
Cache::write($cache, $related, 'posts');
}
//Related posts
debug($related);
注意:在此代码之后,$post 变量不再包含原始帖子。注意相关帖子或使用不同的变量名称。
【问题讨论】:
标签: cakephp cakephp-3.0