Laravel考勤系统:如何计算打卡时长并写入total列?
考勤系统时长计算问题修复方案
你的total方法无法正常运行主要有几个核心问题:
DB::table('attendance')->where('id')语法错误,未指定匹配的ID值,且完全没必要额外查询数据表——你已经通过firstOrFail()拿到了当前考勤记录timeIn和timeOut是字符串格式的时间,直接用数据库原生相减无法得到正确时长差值- 当前流程需要手动调用
total方法,逻辑割裂,应该在下班打卡(timeOut)时自动计算时长
修正后的代码实现
1. 优化User模型的timeOut方法(自动计算总时长)
直接在下班打卡时计算并更新total字段,无需单独的total方法:
public function timeOut() { $manilaTime = Carbon::now('Asia/Manila'); $attendance = $this->employeeAttendance() ->where('date', $manilaTime->toDateString()) ->whereNull('timeOut') ->firstOrFail(); // 解析时间并计算时长(转为小时,保留两位小数) $timeIn = Carbon::createFromFormat('H:i:s', $attendance->timeIn); $timeOut = Carbon::createFromFormat('H:i:s', $manilaTime->format('H:i:s')); $totalHours = $timeIn->diffInMinutes($timeOut) / 60; return $attendance->update([ 'timeOut' => $manilaTime->format('H:i:s'), 'total' => round($totalHours, 2) // 可根据需求调整小数位数 ]); }
2. 简化timeIn方法(可选优化)
无需重复获取auth()->user()->name,当前模型即为登录用户,直接调用$this->name即可:
public function timeIn() { $manilaTime = Carbon::now('Asia/Manila'); return $this->employeeAttendance()->create([ 'name' => $this->name, 'date' => $manilaTime->toDateString(), 'timeIn' => $manilaTime->format('H:i:s'), ]); }
3. 控制器代码保持不变
你的控制器逻辑无需修改:
public function store(Request $request) { $request->user()->timeIn(); return back(); } public function update(Request $request) { $request->user()->timeOut(); return back(); }
关键改进说明
- 用Carbon解析时间字符串,通过
diffInMinutes计算分钟差后转为小时,确保时长计算准确 - 在
timeOut时自动更新total,避免手动调用额外方法,逻辑更连贯 - 移除无效的重复数据库查询,直接操作已获取的考勤记录,提升性能
内容的提问来源于stack exchange,提问作者John Patrick Paguia
相关产品推荐
相关产品推荐

