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

基于Arduino RFID的PHP每日单次考勤实现技术问询

解决RFID每日仅记录一次考勤的问题

我来帮你搞定这个每日仅打卡一次的需求,你的现有代码确实会每次扫描就插入记录,咱们得加个前置检查,顺便还得修复个严重的安全漏洞——直接把用户输入拼进SQL里太危险了!

下面是修改后的完整代码,我会逐部分给你解释:

public function getRFIDAttendanceApi() {
    // 1. 先安全获取并验证RFID UID,避免空值或恶意输入
    $rfid_uid = isset($_REQUEST['uid']) ? trim($_REQUEST['uid']) : '';
    if (empty($rfid_uid)) {
        // 返回清晰的错误提示,方便Arduino端处理
        echo json_encode(['status' => 'error', 'message' => '无效的RFID卡号']);
        return;
    }

    // 2. 验证该RFID是否属于有效用户(保留原逻辑,但改用安全的预处理语句)
    $checkUserSql = "SELECT COUNT(*) AS tot FROM tbl_users WHERE rfid_uid = ?";
    $stmt = $this->conn->prepare($checkUserSql);
    $stmt->bind_param("s", $rfid_uid);
    $stmt->execute();
    $result = $stmt->get_result();
    $userData = $result->fetch_assoc();
    $stmt->close();

    if ($userData['tot'] <= 0) {
        echo json_encode(['status' => 'error', 'message' => '未找到该RFID对应的用户']);
        return;
    }

    // 3. 核心逻辑:检查该用户今日是否已经打过卡
    // 假设你的考勤表有个记录打卡时间的字段`attendance_date`,如果字段名不同请自行替换
    $checkAttendanceSql = "SELECT COUNT(*) AS today_count FROM tbl_attendance 
                           WHERE rfid_uid = ? 
                           AND DATE(attendance_date) = CURDATE()";

    $stmt = $this->conn->prepare($checkAttendanceSql);
    $stmt->bind_param("s", $rfid_uid);
    $stmt->execute();
    $result = $stmt->get_result();
    $attendanceData = $result->fetch_assoc();
    $stmt->close();

    if ($attendanceData['today_count'] > 0) {
        // 用户今日已打卡,直接返回提示,不重复插入
        echo json_encode(['status' => 'info', 'message' => '今日已完成考勤记录']);
        return;
    }

    // 4. 今日未打卡,执行插入操作(依旧用预处理语句保证安全)
    $insertSql = "INSERT INTO tbl_attendance (rfid_uid, attendance_date) 
                  VALUES (?, NOW())";
    $stmt = $this->conn->prepare($insertSql);
    $stmt->bind_param("s", $rfid_uid);
    $flag = $stmt->execute();
    $stmt->close();

    if ($flag) {
        echo json_encode(['status' => 'success', 'message' => '考勤记录成功']);
    } else {
        echo json_encode(['status' => 'error', 'message' => '考勤记录失败:' . $this->conn->error]);
    }
}

关键修改点说明:

  • SQL注入防护:所有SQL操作都用了预处理语句(prepare() + bind_param()),彻底避免了恶意输入篡改SQL的风险,这是生产环境必须做的安全措施。
  • 每日打卡校验:通过DATE(attendance_date) = CURDATE()精准筛选今日的考勤记录,确保同一用户当天只能打卡一次。如果你的考勤表还没有记录时间的字段,建议添加一个attendance_date DATETIME DEFAULT CURRENT_TIMESTAMP。
  • 输入合法性检查:先判断rfid_uid是否为空,过滤无效请求。
  • 友好的反馈机制:用JSON格式返回不同状态的提示,方便Arduino端根据状态触发不同的硬件反馈(比如绿灯亮表示成功,黄灯表示已打卡,红灯表示失败)。

额外小建议:

  • 可以给tbl_attendance表的rfid_uid和attendance_date字段加个联合索引,这样每日打卡检查的查询速度会更快。

内容的提问来源于stack exchange,提问作者Salman Mahmood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:37:12