thinkphp签到功能核心是判断可签性、连续性与奖励匹配,而非单纯每日存记录;需user_sign_log与user_sign_stat双表协同,事务保障一致性,服务端校验日期,幂等防护刷签。

ThinkPHP 实现签到功能,核心在于 用户唯一性识别、日期判断、连续性计算、奖励规则匹配与数据持久化。关键不是“每天存一条”,而是“每次签到前判断是否可签、是否连续、是否触发奖励”,避免重复签到和逻辑漏洞。
一、数据库设计:支撑连续签到的核心结构
需要至少两张表协同工作:
- user_sign_log(签到日志表):记录每次成功签到的时间、用户ID、是否为当日首次(防重复)、签到类型(普通/补签等)
- user_sign_stat(签到统计表):每个用户一条记录,存当前连续天数、历史最高连续天数、最近签到日期、累计签到总天数 —— 用于快速查询和奖励判定,避免每次聚合计算
注意:user_sign_stat 的数据必须与 user_sign_log 严格同步,建议在事务中更新,或用数据库触发器/应用层强一致性保障。
二、签到逻辑:判断 + 更新 + 奖励发放三步闭环
在控制器中编写签到方法,重点处理以下环节:
- 校验登录状态与用户ID:未登录直接拒绝
- 查最近签到日期:从 user_sign_stat 表读取 last_sign_time
-
判断是否可签:
- 若 last_sign_time 是今天 → 已签过,返回“今日已签”
- 若 last_sign_time 是昨天 → 连续签到,连续天数 +1
- 若 last_sign_time 是更早日期(含空)→ 中断,连续天数重置为 1
- 写入日志 & 更新统计:在同一个事务中插入 user_sign_log 并更新 user_sign_stat
- 检查奖励条件并发放:例如连续7天送积分、满30天发勋章。用 switch 或配置化规则匹配 current_continue_days 字段,调用积分服务/勋章服务发放,并记录 reward_log
三、防止刷签:基础防护不可少
签到虽轻量,但需防范恶意请求:
- 接口限流:使用 ThinkPHP 的中间件(如 RateLimit)限制单用户每小时最多调用3次
- 客户端时间不可信:所有日期判断以服务端 time() 为准,禁止接收前端传来的 sign_date 参数
- IP+设备指纹辅助识别(可选):对高频异常 IP 记录并人工复核,不作为主校验,仅作风控参考
- 签到操作幂等:接口支持重复调用不重复生效,靠数据库唯一索引(user_id + date)或业务层加锁(Redis setnx)保证
四、连续天数计算:避免逐条查日志的性能陷阱
不要每次签到都 SELECT * FROM user_sign_log WHERE user_id = ? AND sign_time >= ? ORDER BY sign_time DESC LIMIT 30 来倒推连续性 —— 数据量大时极慢。
- 正确做法是维护 user_sign_stat 表中的 continuous_days 字段,每次签到只做一次 UPDATE,O(1) 复杂度
- 初始化:新用户首次签到,continuous_days = 1,last_sign_time = today
- 补签场景(如有)需单独设计:允许补签近7天内某一天,但不增加连续天数,仅计总天数;补签后需重新校验后续连续性(较复杂,建议初期不开放)
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











