
本文介绍在 Laravel 中通过 Eloquent 关系查询,精准筛选出某个月份内至少有一条有效考勤记录(依据 in_time 字段)的员工,并支持高效统计与展示。
本文介绍在 laravel 中通过 eloquent 关系查询,精准筛选出某个月份内至少有一条有效考勤记录(依据 `in_time` 字段)的员工,并支持高效统计与展示。
在实际人事管理系统中,常需统计“当月有出勤记录的员工总数”或列出这些员工详情。仅使用 has('Attendance') 可筛选出有任意考勤记录的员工,但无法按月份(特别是基于 in_time 的年月范围)精确过滤。因此,需结合 关系存在性约束 + 时间范围条件 来实现。
✅ 正确实现方式:使用 whereHas() 进行带条件的关系查询
has() 方法仅判断关联是否存在,不支持附加查询条件;而 whereHas() 允许你在关联表上添加任意 where 子句,完美适配按 in_time 筛选月份的需求:
use Illuminate\Support\Facades\DB;
$year = 2024;
$month = 10; // 十月
$employees = Employee::whereHas('Attendance', function ($query) use ($year, $month) {
$query->whereYear('in_time', $year)
->whereMonth('in_time', $month);
})->withCount('Attendance') // 预加载每个员工当月考勤次数(优化性能)
->get();? 提示:
withCount('Attendance')会自动添加attendance_count属性到每个$employee实例中,避免 N+1 查询问题。
? 获取员工总数(最常用场景)
若只需返回符合条件的员工总人数(而非完整对象),推荐使用 count() 而非 get()->count(),更高效:
$totalActiveEmployees = Employee::whereHas('Attendance', function ($query) use ($year, $month) {
$query->whereYear('in_time', $year)
->whereMonth('in_time', $month);
})->count();? 在 Blade 模板中展示(含考勤次数)
@foreach ($employees as $employee)
<div>
<strong>{{ $employee->name }}</strong> —
当月出勤 {{ $employee->attendance_count }} 次
</div>
@endforeach⚠️ 注意事项
- 确保
in_time字段为DATETIME或TIMESTAMP类型,且已建立数据库索引(如INDEX(in_time)),否则大数据量下查询性能会显著下降; - 若需支持跨年查询(如“近3个月”),建议改用
whereBetween('in_time', [$start, $end])配合 Carbon 构造时间范围; -
whereYear()和whereMonth()是 Laravel 8+ 原生支持的便捷方法;低版本可替换为:$query->whereRaw('YEAR(in_time) = ?', [$year]) ->whereRaw('MONTH(in_time) = ?', [$month]);
通过 whereHas() 精准控制关联查询条件,配合 withCount() 和数据库索引优化,即可稳健、高效地实现“按月份统计活跃员工”的核心业务需求。

















