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

PHP考勤脚本函数仅返回最后一条日期记录的问题求助

问题分析与解决方案

我仔细看了你的代码,导致只能返回最后一条考勤记录的核心问题有两个:


1. SQL查询的致命问题

你的原查询使用了GROUP BY t.teacher_name,这会强制将每个教师的多条考勤记录合并成一条(数据库会返回分组后的第一条/最后一条记录,取决于引擎),而且你定义了$month和$year变量但完全没用到,导致查询会拉取所有月份的考勤数据,最终每个教师只能拿到一条随机的考勤记录。

修正后的SQL查询

function get_month_attendance(){ 
    global $db, $mybb; 
    $month = date('m'); 
    $year = date('Y'); // 用4位年份更稳妥,避免两位数年份的混淆问题
    // 修改SQL:去掉GROUP BY,加入月份/年份筛选,只拉取当前月的考勤
    $query = $db->query(" 
        SELECT t.*, a.* 
        FROM ".TABLE_PREFIX."teachers t 
        LEFT JOIN ".TABLE_PREFIX."teacher_attendance a 
            ON(a.tid=t.tid) 
            AND a.month = '{$month}'  -- 假设考勤表有month字段,根据你的实际表结构调整
            AND a.year = '{$year}'    -- 假设考勤表有year字段,若用日期字段则用MONTH(a.date)=...
        WHERE t.teacher_approve != '0' 
        ORDER BY t.tid ASC, a.day ASC
    ");

2. PHP数据处理逻辑错误

原代码在while循环中每次只处理单条考勤记录,然后直接生成整行的日期单元格,这意味着每个教师的行只能基于当前循环到的那条考勤记录来渲染,其他日期自然都是默认的'A'。

我们需要先把所有教师的考勤数据按tid分组,存储每个教师每天的考勤信息,再逐个生成行:

重构后的get_month_attendance函数

function get_month_attendance(){ 
    global $db, $mybb; 
    $month = date('m'); 
    $year = date('Y'); 

    // 修正后的SQL查询
    $query = $db->query(" 
        SELECT t.*, a.* 
        FROM ".TABLE_PREFIX."teachers t 
        LEFT JOIN ".TABLE_PREFIX."teacher_attendance a 
            ON(a.tid=t.tid) 
            AND a.month = '{$month}' 
            AND a.year = '{$year}' 
        WHERE t.teacher_approve != '0' 
        ORDER BY t.tid ASC, a.day ASC
    ");

    // 先按tid分组存储教师和对应的全月考勤
    $teachers = [];
    while($row = $db->fetch_array($query)) {
        $tid = $row['tid'];
        if (!isset($teachers[$tid])) {
            // 初始化教师基础信息
            $teachers[$tid] = [
                'tid' => $tid,
                'teacher_name' => $row['teacher_name'],
                'teacher_gender' => $row['teacher_gender'],
                'attendances' => [] // 存储该教师每天的考勤记录
            ];
        }
        // 如果这条是有效的考勤记录(aid存在),按日期存储
        if (!empty($row['aid'])) {
            $teachers[$tid]['attendances'][$row['day']] = $row;
        }
    }

    $month_attendance = ''; 
    foreach($teachers as $t) { 
        // 处理性别前缀
        if ($t['teacher_gender'] == "Male") { 
            $name_prefix = 'Sir '; 
        } elseif ($t['teacher_gender'] == "Female") { 
            $name_prefix = 'Miss '; 
        } else {
            $name_prefix = ''; // 兼容其他性别情况
        } 

        $bg_color = alt_trow(); 
        $month_attendance .= '<tr> 
            <td class="'.$bg_color.'"> 
                <a href="teachers.php?action=view_profile&tid='.$t['tid'].'">'.$name_prefix.$t['teacher_name'].'</a> 
            </td>';

        // 循环生成1-31天的考勤单元格
        for($day = 1; $day <= 31; $day++) {
            $day_str = str_pad($day, 2, '0', STR_PAD_LEFT); // 转成01/02这样的格式,和数据库存储匹配
            // 获取当前教师当天的考勤记录,没有则传null
            $attendance_data = isset($t['attendances'][$day_str]) ? $t['attendances'][$day_str] : null;
            $month_attendance .= get_day_attendance($attendance_data, $day_str);
        }

        $month_attendance .= '</tr>'; 
    } 

    if (!$month_attendance) { 
        $month_attendance = '<tr><td colspan="32" align="center">No Teacher(s).</td></tr>'; 
    } 
    return $month_attendance;
}

3. 修正get_day_attendance函数的小问题

原函数里$attendance_bit变量未初始化就使用,而且需要处理没有考勤记录的情况(传null时直接显示默认的'A'):

function get_day_attendance($a, $day){ 
    $att_text = 'A'; 
    $att_color = '#FF7777'; 

    // 只有当存在考勤记录时才处理
    if ($a !== null) { 
        if ($a['day'] == $day) { 
            if ($a['aid']) // 考勤已记录
            { 
                if (!empty($a['enter_time'])) // 教师在场
                { 
                    $enter_time = 'Entered on: '.date("H:i A", $a['enter_time']); 
                    $exit_time = ''; 
                    if (!empty($a['exit_time'])) // 教师已离开
                    { 
                        $exit_time = '<br />Exited on: '.date("H:i A", $a['exit_time']); 
                    } 
                    $att_text = '<div class="tooltip">P<span class="tooltiptext" style="text-align: left; width: 200px;">'.$enter_time.$exit_time.'</span></div>'; 
                    $att_color = '#00FF54'; 
                } else { 
                    if ($a['leave'] == "1") // 教师请假
                    { 
                        $att_text = '<div class="tooltip">L<span class="tooltiptext" style="text-align: left; width: 200px;">Reason: '.$a['leave_reason'].'</span></div>'; 
                        $att_color = '#F9FF00'; 
                    } 
                } 
            } 
        }
    }

    // 直接返回单元格,不需要未定义的$attendance_bit变量
    return '<td style="background: '.$att_color.';" width="2.5%" align="center">'.$att_text.'</td>';
}

关键说明

  • 如果你考勤表中没有单独的month和year字段,而是用attendance_date这样的日期字段,把SQL里的筛选条件改成:AND MONTH(a.attendance_date) = '{$month}' AND YEAR(a.attendance_date) = '{$year}'
  • 重构后的数据处理逻辑会先把每个教师的所有考勤记录收集起来,再逐个日期匹配渲染,这样就能正确展示全月的考勤状态了

内容的提问来源于stack exchange,提问作者Imran Omer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:47:37