在Laravel中按数量顺序排列多对多态

时间:2019-01-13 16:05:58

标签: laravel laravel-5 eloquent

让我们以文档中的示例为例:https://laravel.com/docs/5.7/eloquent-relationships#many-to-many-polymorphic-relations很容易获得所有posts且其tags计数为Post::withCount('tags')->get()

但是如何获取所有tags及其使用计数?按最常用/最不常用的顺序排序。

如果我做Tag::withCount(['video', 'post'])->get(),我将有2个属性videos_countposts_count。就我而言,我想要一个唯一的taggables_count,它将是两者之和。在理想情况下,通过添加子选择查询数据透视表。

2 个答案:

答案 0 :(得分:0)

我建议您简单地进行您已经进行的通话,即Tag::withCount(['video', 'post'])->get(),并将其添加到您的Tag模型中:

// Tag.php
class Tag
{
  ...
  // Create an attribute that can be called using 'taggables_count'
  public function getTaggablesCountAttribute()
  {
    return $this->videos_count + $this->posts_count;
  }
  ...
}

,然后在循环中(或使用集合中的项目):

@foreach($tags as $tag)
  {{ $tag->taggables_count }}
@endforeach

此设置要求您使用withCount['video', 'post']获取标签。否则,您可能会得到0来换取$tag->taggables_count

如果您真的担心速度,则必须手动创建查询并在其中进行添加。

答案 1 :(得分:0)

因此,在进行更多搜索之后,我发现仅凭一个查询就无法执行此操作,原因是在mysql中我们无法对子子集结果进行选择。因此,执行Tag::withCount(['videos', 'posts'])并尝试对查询videos_countposts_count求和将不起作用。我最好的方法是创建一个在数据透视表中读取结果的范围:

public function scopeWithTaggablesCount($query) {
    if (is_null($query->getQuery()->columns)) {
        $query->select($query->getQuery()->from . '.*');
    }

    $query->selectSub(function ($query) {
        $query->selectRaw('count(*)')
            ->from('taggables')
            ->whereColumn('taggables.tag_id', 'tags.id');
    }, 'taggables_count');

    return $query;
}

要使用它:

$tags = Tag::withTaggablesCount()->orderBy('name', 'ASC')->get();

因此,现在每个标签都有一个taggables_count,它可以用于order by。希望它可以帮助别人。