Вопрос

I'm trying to create a tag cloud in Laravel 4.1, tags can belong to many posts, and posts can have many tags. I'm using a pivot table to achieve this (post_tag). So far I've come up with this to fetch the tags and check how many times it's used:

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);
}

I pass Tag::all() to the above function. Obviously that's going to fire a crazy amount of queries on the database, which is what I'm trying to avoid. Normally you'd use eager loading to fix this problem, but it seems the documentation does not mention anything about eager loading pivot tables in combination with aggregates.

I hope someone can shine a light on how to optimize this current function or can point me in the right direction of a better alternative.

Это было полезно?

Решение 2

I believe you have a many-to-many relationship with posts in your tags table like this:

public function posts()
{
    return $this->belongsToMany('Post');
}

So, you are able to do something like this:

$tags = Tag::with('posts')->get();

Then you may loop though the tags to find out how many posts each tag contains, like this:

foreach($tags as $tag) {
    $tag->posts->count();
};

So, you may write your function like this:

public function scopeTagCloude($query) {
    $cloud = [];
    $query->with('posts')->get()->each(function($tag) use (&$cloud) {
        $cloud[$tag['slug']] = $tag->posts->count();
    });
    return $cloud;
}

You may call this function like this:

$tagCloude = Tag::tagCloude();

If you dd($tagCloude) then you'll get something like this (example is taken from my blog app):

array (size=4)
   'general' => int 4
   'special' => int 5
   'ordinary' => int 5
   'extra_ordinary' => int 2

Другие советы

Sometimes it's just hard reduce them, but Laravel Cache is your friend:

$users = DB::table('users')->remember(10)->get();

It will remember your query for 10 minutes.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top