Laravel 12按天统计用户访问记录的核心是用DATE(created_at)分组+Carbon处理日期范围+DB::table或Eloquent聚合;需确保created_at为datetime/timestamp类型并正确写入时间;通过selectRaw('DATE(created_at) as date, COUNT(*) as count')配合groupBy实现按天计数,再用Carbon补全空日期可得连续7天含零值数组。

在 Laravel 12 中按天统计用户每日访问记录,核心是「用数据库时间字段分组 + Carbon 处理日期范围 + Eloquent/Query Builder 聚合」。不依赖外部日志轮转,而是直接查业务表(如 user_visits、access_logs 或自定义埋点表),按 DATE(created_at) 聚合计数即可。
确保数据表有可查询的时间字段
你的访问记录表必须包含一个带时区感知的 datetime 类型字段(推荐 created_at),且已正确写入用户访问时间。Laravel 默认迁移中该字段已存在,若为自定义表,请确认:
- 字段类型是
datetime或timestamp(非date) - 插入数据时使用了
now()、Carbon::now()或模型自动填充 - 避免用字符串拼接日期,否则无法准确分组
用 DB 查询构造器按天聚合
最简洁可靠的方式是用 DB::table() 配合 selectRaw 和 groupBy:
$dailyStats = DB::table('user_visits')
->selectRaw('DATE(created_at) as date, COUNT(*) as count')
->whereBetween('created_at', [now()->subDays(7), now()])
->groupBy('date')
->orderBy('date')
->get();
返回结果类似:
[{"date":"2026-10-14","count":42},{"date":"2026-10-15","count":58},...]
注意:DATE(created_at) 在 MySQL 中会截断为 YYYY-MM-DD,适配按天分组;PostgreSQL 用 DATE(created_at) 同样有效,SQLite 用 DATE(created_at) 或 strftime('%Y-%m-%d', created_at)。
补全“空日期”让前端图表更友好
原始 SQL 不会返回没访问的日期(比如某天为 0)。如需完整 7 天连续数据(含 0 值),可在 PHP 层补全:
$range = collect(Carbon::now()->subDays(6)->daysUntil(now()))
->mapWithKeys(fn($d) => [$d->format('Y-m-d') => 0]);
$statsMap = $dailyStats->pluck('count', 'date')->all();
$result = $range->merge($statsMap)->sortKeys()->values();
这样得到的是严格按顺序排列的 7 个整数数组,可直接传给 Chart.js 或其他图表库。
封装成 Eloquent 方法或查询作用域
若访问记录存于 UserVisit 模型中,建议加一个本地作用域提升复用性:
// app/Models/UserVisit.php
public function scopeForDateRange(Builder $builder, Carbon $start, Carbon $end)
{
return $builder->selectRaw('DATE(created_at) as date, COUNT(*) as count')
->whereBetween('created_at', [$start, $end])
->groupBy('date')
->orderBy('date');
}
// 控制器中调用
$dailyStats = UserVisit::forDateRange(now()->subDays(30), now())->get();
这样后续扩展按周(WEEK(created_at))、按月(DATE_FORMAT(created_at, "%Y-%m"))也只需改 select 和 groupBy 表达式。


















