You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();

补充优化点

  1. 原查询中的havingBetween建议替换为whereBetween,having通常用于聚合结果筛选,直接使用whereBetween更符合查询逻辑:
->whereBetween('attendances.date', [$dateFrom, $dateTo])
  1. 如果不需要补全缺失日期的状态,可简化为直接提取当前学生的日期和状态数组:
// 简化版(不补全缺失日期)
$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:45:31