Laravel实现统计30天周期应出勤天数与考勤数据的方法
现有代码存在的问题
total_hari()缺少空值兜底:当指定周期内无排班数据时,直接访问集合索引0的属性会触发未定义报错- 周期计算逻辑不符合需求:当前取「上月26日到当日」为统计区间,周期长度随实际日期浮动,无法固定实现30天的统计跨度
- 核心计算逻辑被注释:
alpha_bulan_ini()方法直接返回应出勤总天数,没有执行「应出勤总天数 - 实际出勤记录数」的差值计算,导致前端两列展示内容重复 - 模板判断逻辑冗余:
isset($key->absensihari)无实际业务作用,会导致无关联出勤记录的员工不展示统计值 - 查询写法冗余:用
select(DB::raw('count(*))->get()的写法效率低,数据库层直接提供了count()方法,无需拉取全量匹配行再做统计
修正后实现代码
Model层
public function total_hari($karyawanId) { // 固定30天统计周期:起点为上月26日,向后顺延29天,包含首尾共30天 $periodStart = date("Y-m-26", strtotime("-1 months")); $periodEnd = date("Y-m-d", strtotime($periodStart . " +29 days")); return DB::table('working_schedule') ->where('karyawan_id', $karyawanId) ->whereNull('deleted_at') ->whereBetween('date', [$periodStart, $periodEnd]) ->count(); } public function alpha_bulan_ini($karyawanId) { $periodStart = date("Y-m-26", strtotime("-1 months")); $periodEnd = date("Y-m-d", strtotime($periodStart . " +29 days")); $totalShouldAttend = $this->total_hari($karyawanId); $actualAttendCount = DB::table('karyawan_absensi') ->where('karyawan_id', $karyawanId) ->whereNull('deleted_at') ->whereBetween('tanggal', [$periodStart, $periodEnd]) ->count(); // 按业务逻辑返回缺勤数 = 应出勤总天数 - 实际出勤数 return $totalShouldAttend - $actualAttendCount; }
模板层(index.blade.php)
<td style='text-align:center'>{{ $key->total_hari($key->karyawan_id) }}</td> <td style='text-align:center'>{{ $key->alpha_bulan_ini($key->karyawan_id) }}</td>
改动说明
- 周期固定:通过在起点日期上顺延29天计算终点,保证首尾包含的区间刚好为30天,完全匹配统计目标,不会因为当月天数多少、当日是月中/月末导致周期长度不足
- 稳定性提升:数据库
count()方法会自动返回整数结果,无匹配行时返回0,不需要额外的空值判断,彻底避免未定义索引报错 - 性能优化:统计逻辑直接在数据库层执行,不需要拉取全量排班、出勤数据到PHP进程再做计数,大幅降低大表场景下的查询开销
- 计算逻辑对齐:恢复差值计算,前端第一列展示30天周期内的应出勤总天数,第二列展示核算后的缺勤数,完全匹配业务需求
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

