feat: add similar_media

This commit is contained in:
2026-06-13 13:16:17 +03:30
parent 3a2ed286b6
commit 00d8b9687b
+48 -1
View File
@@ -377,13 +377,15 @@ public function show($id)
// Get user's specific comment
$userComment = $media->userComment();
// Get paginated comments
$comments = $media->comments()
->with('user')
->latest()
->paginate(15);
$similarMedia = $this->similarMedia($media);
return response()->json([
'id' => $media->id,
'title' => $media->title,
@@ -417,8 +419,53 @@ public function show($id)
'user_comment_id' => $media->user_comment_id,
],
'comments' => $comments,
'similar_media' => $similarMedia,
]);
}
// Media that shares categories / subcategories / tags with the given one,
// ranked by how much they overlap. Excludes the media itself.
private function similarMedia(Media $media, int $limit = 5)
{
$categoryIds = $media->categories->pluck('id')->all();
$subCategoryIds = $media->subCategories->pluck('id')->all();
$tagIds = $media->tags->pluck('id')->all();
if (!$categoryIds && !$subCategoryIds && !$tagIds) {
return collect();
}
$userId = auth()->id();
return Media::query()
->where('media.id', '!=', $media->id)
->where('media.type', $media->type)
->where(function ($q) use ($userId) {
$q->where('visibility', 'public')->orWhere('user_id', $userId);
})
->where(function ($q) use ($categoryIds, $subCategoryIds, $tagIds) {
if ($categoryIds) {
$q->orWhereHas('categories', fn ($c) => $c->whereIn('categories.id', $categoryIds));
}
if ($subCategoryIds) {
$q->orWhereHas('subCategories', fn ($s) => $s->whereIn('sub_categories.id', $subCategoryIds));
}
if ($tagIds) {
$q->orWhereHas('tags', fn ($t) => $t->whereIn('tags.id', $tagIds));
}
})
->withCount([
'categories as category_matches' => fn ($c) => $c->whereIn('categories.id', $categoryIds ?: [0]),
'subCategories as subcategory_matches' => fn ($s) => $s->whereIn('sub_categories.id', $subCategoryIds ?: [0]),
'tags as tag_matches' => fn ($t) => $t->whereIn('tags.id', $tagIds ?: [0]),
])
->with(['image', 'detailImage', 'categories', 'subCategories', 'tags'])
->orderByRaw('(category_matches + subcategory_matches + tag_matches) desc')
->orderByDesc('created_at')
->limit($limit)
->get();
}
public function rate(Request $request, $mediaId)
{
$request->validate([