我正在从事一个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