大多数在Laravel中对许多多态性的标签进行排序



我正在从事一个Laravel项目,我需要为多个雄辩的模型实现标记功能,因此我为此任务选择了许多至今的多态性关系。我需要显示相关的标签,并通过侧边栏部分中的大多数用于特定模型进行排序。

这些模型(表(需要标记功能,目前:

  • 图片(ID,文件名,...(
  • 视频(ID,文件名,...(
  • 文章(id,slug,title,摘要,内容...(

我用标签枢轴表制作了标签模型。

  • 标签(ID,名称,描述(
  • taggables(id,tag_id,taggable_type,taggable_id(

所有这些模型均通过morphToMany与标签模型和标签模型通过morphedByMany通过惯例连接,与Laravel 5.6 Docs相同,所有这些都可以正常工作。

这是标记枢轴模式:

<?php
class CreateTaggablesTable extends Migration {
    public function up() {
        Schema::create('taggables', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('tag_id');
            $table->morphs('taggable');
            $table->unique(['tag_id', 'taggable_type', 'taggable_id']); // Only unique
        });
    }
}

在第一个时刻,客户要求仅在侧边栏上显示它们,所以我这样做了:

<?php
namespace App; 
use IlluminateDatabaseEloquentModel;
class Tag extends Model {
    public static function fetchLatest(int $limit) {
        return static::has('articles')->latest()->take($limit)->pluck('name');        
    }
}

该客户端希望按大多数使用的方式对它们进行排序,因此我决定以某种方式计算它们出现在Taggables Pivot表中的次数。我最终得到了:

<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Tag extends Model {
    public static function fetchByMostUsed(int $limit = 15, string $model = 'AppArticle') 
    {
        return static::select('tags.id', 'tags.name')
            ->join('taggables', 'tags.id', '=', 'taggables.tag_id')
            ->selectRaw('count(taggables.tag_id) as aggregate')
            ->where('taggables.taggable_type', '=', $model)
            ->groupBy('tags.id', 'tags.name')
            ->orderBy('aggregate', 'desc')
            ->limit($limit)
           ->pluck('name');
   }
}

如果您喜欢更多纯SQL查询,则看起来像:

select `tags`.`id`, `tags`.`name`, count(taggables.tag_id) as aggregate from `tags` inner join `taggables` on `tags`.`id` = `taggables`.`tag_id` where `taggables`.`taggable_type` = 'AppArticle' and `tags`.`deleted_at` is null group by `tags`.`id`, `tags`.`name` order by `aggregate` desc limit 15

这有效,但是有什么更简单,更优雅的方法可以做到这一点吗?至少,要摆脱我需要通过变量进行硬码或通过特定模型(taggable_type(的事实?我宁愿制作3种不同的方法(对于每个模型而不是代码中的任何地方进行硬码。

withCount('relationship')添加了其他列的选择。

Article::withCount('tags')->orderBy('tags_count', 'desc')->get();
Picture::withCount('tags')->orderBy('tags_count', 'desc')->get();
Video::withCount('tags')->orderBy('tags_count', 'desc')->get();

laravel文档:https://laravel.com/docs/5.6/eloquent-relationships#counting与与之相关的models

最新更新