Laravel 5.5报错:字符串无法调用format(),求考勤时长格式化方案
解决Laravel 5.5中
Call to a member function format() on string错误 这个错误的核心原因很明确:你通过DB::sum('duration')获取到的$total_duration是数值或字符串类型,并不是Carbon日期对象,所以自然不能调用format()方法。下面分两种常见场景给你针对性解决方案:
场景1:duration字段存储的是秒数(整数)
如果你的attendances表中duration字段存的是每次考勤的时长秒数(比如1800代表30分钟),可以在控制器里直接把总秒数格式化为H:i:s格式,再传给视图:
修改控制器代码
public function index(Request $request) { $id = Auth::id(); // 获取总秒数 $total_seconds = DB::table('attendances') ->where('teacher_id', '=', $id) ->sum('duration'); // 把总秒数格式化为时分秒(用gmdate避免时区干扰) $total_duration_formatted = gmdate('H:i:s', $total_seconds); // 如果你习惯用Carbon,也可以这么写: // $total_duration_formatted = \Carbon\Carbon::createFromTimestamp($total_seconds)->format('H:i:s'); return view('teachers.attendance.index', compact('teacher', 'attendances', 'att_id', 'total_duration_formatted')); }
修改视图代码
直接输出格式化好的字符串即可:
<tr> <td colspan="4">Total</td> <td>{{ $total_duration_formatted }}</td> </tr>
场景2:duration字段存储的是时间格式字符串(比如01:30:00)
如果duration字段存的是H:i:s格式的字符串,直接用sum()会得到错误结果(MySQL会把时间字符串当成数值乱加)。这时候需要先把每个duration转成秒数再求和:
修改控制器代码
public function index(Request $request) { $id = Auth::id(); // 用TIME_TO_SEC把时间转成秒数,再求和 $total_seconds = DB::table('attendances') ->where('teacher_id', '=', $id) ->select(DB::raw('SUM(TIME_TO_SEC(duration)) as total_seconds')) ->value('total_seconds'); // 格式化总秒数为时分秒,处理总和为null的边界情况 $total_duration_formatted = gmdate('H:i:s', $total_seconds ?? 0); return view('teachers.attendance.index', compact('teacher', 'attendances', 'att_id', 'total_duration_formatted')); }
修改视图代码
和场景1一致,直接输出格式化后的字符串:
<tr> <td colspan="4">Total</td> <td>{{ $total_duration_formatted }}</td> </tr>
额外提醒
- 如果你的
duration字段是MySQL的TIME类型,处理方式和场景2完全一致,必须先转成秒数再求和,否则直接sum会得到毫无意义的字符串结果。 - 优先用
gmdate而非date,因为我们计算的是纯时长,不需要受服务器时区影响。
内容的提问来源于stack exchange,提问作者Rashed Hasan
相关产品推荐
相关产品推荐

