我正在尝试在Laravel 4.1中创建标签云,标签可以属于许多帖子,帖子可以有很多标签。我正在使用数据透视表来实现这一点(post_tag)。到目前为止,我已经想出了这个来获取标签并检查它使用了多少次:
public static function tagCloud($tags, $max = 10) {
foreach($tags->toArray() as $tag) {
$count = DB::table('post_tag')
->where('tag_id', $tag['id'])
->count();
$cloud[$tag['slug']] = $count;
}
sd($cloud);
}
我将Tag::all()
传递给上述函数。显然,这将在数据库上触发大量查询,这是我试图避免的。通常,您会使用预先加载来解决此问题,但文档似乎没有提到有关预先加载数据透视表与聚合结合使用的任何内容。
我希望有人能阐明如何优化当前功能,或者可以为我指出更好的选择的正确方向。
有时很难减少它们,但 Laravel Cache 是你的朋友:
$users = DB::table('users')->remember(10)->get();
它将记住您的查询 10 分钟。
我相信你和tags
表中的posts
有many-to-many
关系,如下所示:
public function posts()
{
return $this->belongsToMany('Post');
}
因此,您可以执行以下操作:
$tags = Tag::with('posts')->get();
然后,您可以遍历标签以找出每个标签包含多少帖子,如下所示:
foreach($tags as $tag) {
$tag->posts->count();
};
因此,您可以像这样编写函数:
public function scopeTagCloude($query) {
$cloud = [];
$query->with('posts')->get()->each(function($tag) use (&$cloud) {
$cloud[$tag['slug']] = $tag->posts->count();
});
return $cloud;
}
你可以像这样调用这个函数:
$tagCloude = Tag::tagCloude();
如果你dd($tagCloude)
,那么你会得到这样的东西(示例取自我的博客应用程序):
array (size=4)
'general' => int 4
'special' => int 5
'ordinary' => int 5
'extra_ordinary' => int 2