php实现日榜周榜月榜
实现日榜、周榜、月榜的PHP方案
通过时间范围筛选数据并排序,结合数据库查询和缓存机制实现榜单功能。
数据库表设计
假设存储用户得分的表结构如下:
CREATE TABLE user_scores (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
日榜实现
获取当日0点到当前时间的数据:

$todayStart = date('Y-m-d 00:00:00');
$todayEnd = date('Y-m-d H:i:s');
$dailyRanking = DB::table('user_scores')
->select('user_id', DB::raw('SUM(score) as total_score'))
->whereBetween('created_at', [$todayStart, $todayEnd])
->groupBy('user_id')
->orderByDesc('total_score')
->limit(10)
->get();
周榜实现
获取本周一0点到当前时间的数据:
$weekStart = date('Y-m-d 00:00:00', strtotime('last Monday'));
$weekEnd = date('Y-m-d H:i:s');
$weeklyRanking = DB::table('user_scores')
->select('user_id', DB::raw('SUM(score) as total_score'))
->whereBetween('created_at', [$weekStart, $weekEnd])
->groupBy('user_id')
->orderByDesc('total_score')
->limit(10)
->get();
月榜实现
获取本月1日0点到当前时间的数据:

$monthStart = date('Y-m-01 00:00:00');
$monthEnd = date('Y-m-d H:i:s');
$monthlyRanking = DB::table('user_scores')
->select('user_id', DB::raw('SUM(score) as total_score'))
->whereBetween('created_at', [$monthStart, $monthEnd])
->groupBy('user_id')
->orderByDesc('total_score')
->limit(10)
->get();
性能优化方案
使用Redis缓存榜单结果,避免频繁查询数据库:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 日榜缓存键
$dailyKey = 'ranking:daily:' . date('Ymd');
if (!$redis->exists($dailyKey)) {
// 从数据库获取并存入Redis
$dailyData = /* 数据库查询逻辑 */;
$redis->setex($dailyKey, 86400, json_encode($dailyData));
}
$dailyRanking = json_decode($redis->get($dailyKey));
定时任务更新
通过Crontab定时生成榜单:
0 0 * * * /usr/bin/php /path/to/update_daily_ranking.php
0 0 * * 1 /usr/bin/php /path/to/update_weekly_ranking.php
0 0 1 * * /usr/bin/php /path/to/update_monthly_ranking.php
数据结构优化
对于大规模数据,考虑使用专门的结构存储排名:
// Redis有序集合实现实时排名
$redis->zAdd('daily_scores', $score, $user_id);
$dailyTop10 = $redis->zRevRange('daily_scores', 0, 9, true);
以上方案可根据实际业务需求调整时间范围定义和排序规则,缓存过期时间建议设置为对应榜单周期的自然结束时间。






