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

如何检查同用户同日记录是否存在并实现条件插入数据

实现每日签到功能(避免重复记录)

这是个非常常见的日常签到场景需求,我一步步帮你落地实现:

1. 先搞定数据库表结构

首先你的签到表(比如命名为user_checkins)得有合适的字段和约束,核心是给userid和checkin_date加联合唯一索引——既能在数据库层面直接阻止重复插入,还能加快查询效率。

创建表的SQL示例:

CREATE TABLE user_checkins (
    id INT AUTO_INCREMENT PRIMARY KEY,
    userid INT NOT NULL,
    companyid INT NOT NULL,
    checkin_date DATE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    -- 关键约束:同一用户同一天只能有一条签到记录
    UNIQUE KEY unique_user_daily_checkin (userid, checkin_date)
);

2. 写checkin.php的核心逻辑

这里有两种靠谱的实现方式,你可以根据需求选:

方式一:先查询再插入(直观易懂)

先检查当前用户今天有没有签到记录,没有就插入,否则返回提示。务必用预处理语句防SQL注入:

<?php
// 假设你已经通过PDO建立了数据库连接
$pdo = new PDO('mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4', '用户名', '密码');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// 从会话获取当前用户和公司ID(登录后应该存在$_SESSION里)
$userid = $_SESSION['user_id'];
$companyid = $_SESSION['company_id'];
$today = date('Y-m-d'); // 只取日期部分,确保按天判断签到

try {
    // 查询是否存在今日签到记录
    $stmt = $pdo->prepare("SELECT id FROM user_checkins WHERE userid = ? AND checkin_date = ?");
    $stmt->execute([$userid, $today]);
    $hasRecord = $stmt->rowCount() > 0;

    if ($hasRecord) {
        echo json_encode(['status' => 'error', 'message' => '记录已存在']);
    } else {
        // 插入新签到记录
        $stmt = $pdo->prepare("INSERT INTO user_checkins (userid, companyid, checkin_date) VALUES (?, ?, ?)");
        $stmt->execute([$userid, $companyid, $today]);
        echo json_encode(['status' => 'success', 'message' => '签到成功']);
    }
} catch (PDOException $e) {
    echo json_encode(['status' => 'error', 'message' => '服务器出错:' . $e->getMessage()]);
}
?>

方式二:利用数据库约束直接插入(更高效)

因为已经加了联合唯一索引,我们可以用INSERT IGNORE简化逻辑,不用提前查询,还能避免并发场景下的竞态问题:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=你的数据库名;charset=utf8mb4', '用户名', '密码');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$userid = $_SESSION['user_id'];
$companyid = $_SESSION['company_id'];
$today = date('Y-m-d');

try {
    // 用INSERT IGNORE:如果违反唯一约束,自动忽略插入操作
    $stmt = $pdo->prepare("INSERT IGNORE INTO user_checkins (userid, companyid, checkin_date) VALUES (?, ?, ?)");
    $stmt->execute([$userid, $companyid, $today]);

    if ($stmt->rowCount() > 0) {
        echo json_encode(['status' => 'success', 'message' => '签到成功']);
    } else {
        echo json_encode(['status' => 'error', 'message' => '记录已存在']);
    }
} catch (PDOException $e) {
    echo json_encode(['status' => 'error', 'message' => '服务器出错:' . $e->getMessage()]);
}
?>

3. 前端交互(给用户友好反馈)

用户点击签到按钮后,用AJAX请求后端并显示结果:

<button id="checkinBtn">点击签到</button>
<div id="tipMessage"></div>

<script>
document.getElementById('checkinBtn').addEventListener('click', function() {
    const btn = this;
    btn.disabled = true; // 防止重复点击
    fetch('checkin.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    })
    .then(res => res.json())
    .then(data => {
        const tip = document.getElementById('tipMessage');
        tip.textContent = data.message;
        // 给不同状态加样式区分
        tip.style.color = data.status === 'success' ? 'green' : 'red';
        btn.disabled = false;
    })
    .catch(err => {
        document.getElementById('tipMessage').textContent = '请求失败,请重试';
        document.getElementById('tipMessage').style.color = 'red';
        btn.disabled = false;
    });
});
</script>

几个重要提醒

  • 永远不要直接把userid、companyid拼进SQL语句,预处理语句是防注入的基础。
  • 日期处理要统一:要么用PHP的date('Y-m-d'),要么用MySQL的CURDATE(),别带时间部分,不然同一用户同一天不同时间签到会被当成不同记录。
  • 确保用户是已登录状态,避免未授权的恶意签到请求。

内容的提问来源于stack exchange,提问作者OWAIS ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:42:19