我正在开发一个Laravel项目,我需要为多个Eloquent模型实现标记功能,因此我为此任务选择了多对多的多态关系。我需要显示相关的标签,并按照侧边栏部分中用于特定模型的大多数进行排序。
目前,这些模型(表格)需要标记功能:
我用taggables数据透视表制作了Tag模型。
所有这些模型都通过morphToMany
与Tag模型和Tag模型按惯例通过morphedByMany
关系连接,与Laravel 5.6 docs中的方式相同,并且一切正常。
这是taggables pivot schema:
<?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 Illuminate\Database\Eloquent\Model;
class Tag extends Model {
public static function fetchLatest(int $limit) {
return static::has('articles')->latest()->take($limit)->pluck('name');
}
}
之后,客户希望按照最常用的方式对它们进行排序,因此我决定以某种方式计算它们在taggables数据透视表中出现的次数。我最终得到了这个:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model {
public static function fetchByMostUsed(int $limit = 15, string $model = 'App\Article')
{
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` = 'App\Article' and `tags`.`deleted_at` is null group by `tags`.`id`, `tags`.`name` order by `aggregate` desc limit 15
这样可行,但有没有更简单,更优雅的方法呢?至少,要摆脱我需要通过变量硬编码或传递特定模型(taggable_type)的事实?我宁愿制作3种不同的方法(对于每种模型而不是在代码中的任何地方进行硬编码。
答案 0 :(得分:-1)
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-related-models