PHP Laravel中重组考勤数组:按学生分组聚合状态与日期
现有输出数组
以下是获取到的考勤数组输出:
[0] => stdClass Object ( [status] => P [date] => 10/02/2022 [firstname] => testing 10 [subject_id] => 5 ) [1] => stdClass Object ( [status] => A [date] => 10/02/2022 [firstname] => arsalan 12 [subject_id] => 5 ) [2] => stdClass Object ( [status] => L [date] => 10/02/2022 [firstname] => khan 4 [subject_id] => 5 ) [3] => stdClass Object ( [status] => P [date] => 10/03/2022 [firstname] => testing 10 [subject_id] => 5 ) [4] => stdClass Object ( [status] => L [date] => 10/03/2022 [firstname] => arsalan 12 [subject_id] => 5 ) [5] => stdClass Object ( [status] => A [date] => 10/03/2022 [firstname] => khan 4 [subject_id] => 5 ) [6] => stdClass Object ( [status] => P [date] => 10/04/2022 [firstname] => testing 10 [subject_id] => 5 ) [7] => stdClass Object ( [status] => P [date] => 10/04/2022 [firstname] => arsalan 12 [subject_id] => 5 ) [8] => stdClass Object ( [status] => P [date] => 10/04/2022 [firstname] => khan 4 [subject_id] => 5 ) [9] => stdClass Object ( [status] => P [date] => 10/05/2022 [firstname] => testing 10 [subject_id] => 5 ) [10] => stdClass Object ( [status] => A [date] => 10/05/2022 [firstname] => arsalan 12 [subject_id] => 5 )
控制器查询代码
这是在控制器中使用的查询代码:
$attendance = DB::table('attendances') ->join('users', 'attendances.user_id', '=', 'users.id') ->havingBetween('attendances.date', array($dateFrom, $dateTo)) ->having('attendances.subject_id','=',$ideas[0]) ->orderBy('attendances.date','asc') ->get(['attendances.status','attendances.date','users.firstname','attendances.subject_id'])->toArray();
期望输出数组
需要将数组转换为如下结构:
[0] => stdClass Object ( [status] => [ P, P, P, P ] [date] => [ 10/02/2022, 10/03/2022, 10/04/2022, 10/05/2022, ] [firstname] => testing 10 [subject_id] => 5 ) [1] => stdClass Object ( [status] => [ A, L, P, A ] [date] => [ 10/02/2022, 10/03/2022, 10/04/2022, 10/05/2022, ] [firstname] => arsalan 12 [subject_id] => 5 ) [2] => stdClass Object ( [status] => [ L, A, P, '' ] [date] => [ 10/02/2022, 10/03/2022, 10/04/2022, 10/05/2022, ] [firstname] => khan 4 [subject_id] => 5 )
需求说明
需要将现有按日期分散的考勤记录,按学生(firstname)分组,将每个学生的所有考勤状态和对应日期分别整理为数组,用于以表格形式展示考勤(非每日考勤场景)。
解决方案
利用Laravel集合完成分组和数据重组,代码如下:
// 将查询结果转为集合 $attendanceCollection = collect($attendance); // 获取所有唯一的考勤日期(用于补全学生缺失的日期记录) $allDates = $attendanceCollection->pluck('date')->unique()->sort()->values()->toArray(); // 按学生分组并重组数据 $groupedAttendance = $attendanceCollection->groupBy('firstname')->map(function ($items) use ($allDates) { $completeStatuses = []; // 遍历所有日期,匹配对应学生的考勤状态 foreach ($allDates as $date) { $record = $items->firstWhere('date', $date); $completeStatuses[] = $record ? $record->status : ''; // 无记录时用空字符串,可按需修改默认值 } return (object)[ 'firstname' => $items->first()->firstname, 'subject_id' => $items->first()->subject_id, 'date' => $allDates, 'status' => $completeStatuses, ]; })->values()->toArray();
补充优化点
- 原查询中的
havingBetween建议替换为whereBetween,having通常用于聚合结果筛选,直接使用whereBetween更符合查询逻辑:
->whereBetween('attendances.date', [$dateFrom, $dateTo])
- 如果不需要补全缺失日期的状态,可简化为直接提取当前学生的日期和状态数组:
// 简化版(不补全缺失日期) $groupedAttendance = $attendanceCollection->groupBy('firstname')->map(function ($items) { return (object)[ 'firstname' => $items->first()->firstname, 'subject_id' => $items->first()->subject_id, 'date' => $items->pluck('date')->toArray(), 'status' => $items->pluck('status')->toArray(), ]; })->values()->toArray();
内容的提问来源于stack exchange,提问作者Arsalan Khan
相关产品推荐
相关产品推荐

