Add trending videos page with YouTube-style algorithm

- Trending algorithm based on:
  - Recent views (last 48h): 70% weight
  - View velocity (views/hour): 15% weight
  - Recency bonus: 10% weight
  - Like count: 5% weight
- Excludes videos older than 10 days
- Filter options: Today/This Week/This Month
- Added route, controller method, and view
- Updated nav to link to trending page
This commit is contained in:
ghassan committed 2026-03-03 21:30:44 +03:00
1 parent 59870862db
commit 9ad842dcd5
5 files changed
+327 -2

No files matched your search

+43
View File
@@ -395,4 +395,47 @@ class VideoController extends Controller
return response()->download($path, $filename);
}
// Trending videos page
public function trending(Request $request)
{
$hours = $request->get('hours', 48); // Default: 48 hours
$limit = $request->get('limit', 50);
// Validate parameters
$hours = min(max($hours, 24), 168); // Between 24h and 7 days
$limit = min(max($limit, 10), 100);
// Get trending videos using the scope with raw score calculation
$trendingVideos = \DB::table('videos')
->select('videos.*',
\DB::raw('(
(SELECT COUNT(*) FROM video_views vv WHERE vv.video_id = videos.id AND vv.watched_at >= DATE_SUB(NOW(), INTERVAL ' . $hours . ' HOUR)) * 0.70 +
(SELECT COUNT(*) FROM video_views vv WHERE vv.video_id = videos.id AND vv.watched_at >= DATE_SUB(NOW(), INTERVAL ' . $hours . ' HOUR)) / ' . $hours . ' * 100 * 0.15 +
GREATEST(0, 1 - TIMESTAMPDIFF(HOUR, videos.created_at, NOW()) / 240) * 50 * 0.10 +
(SELECT COUNT(*) FROM video_likes vl WHERE vl.video_id = videos.id) * 0.1 * 0.05
) as trending_score')
)
->where('visibility', 'public')
->where('status', 'ready')
->where('created_at', '>=', now()->subDays(10))
->having('trending_score', '>', 0)
->orderByDesc('trending_score')
->limit($limit)
->get();
// Load user relationship
$trendingVideos = $trendingVideos->map(function ($video) {
$video->user = \App\Models\User::find($video->user_id);
$video->view_count = \DB::table('video_views')->where('video_id', $video->id)->count();
$video->like_count = \DB::table('video_likes')->where('video_id', $video->id)->count();
return $video;
});
return view('videos.trending', [
'videos' => $trendingVideos,
'hours' => $hours,
'limit' => $limit,
]);
}
}