codeigniter用户签到需解决重复提交、跨天错乱、记录冲突三大问题:checktimein()须传$date严格匹配logdate(date类型),用count_all_results()校验;save()须先查v_id+logdate是否存在再插入,并建唯一索引;update()签退须按id降序定位当日status=0最新记录;前后端均需防重复请求。

CodeIgniter 实现用户签到功能,核心不是“怎么写个表单提交”,而是解决三个实际问题:同一天重复提交、跨天逻辑错乱、数据库记录冲突。直接上关键点。
checktimein() 必须传入 $date 参数做严格日期匹配
很多初学者只查 V_ID,结果昨天签到的记录被当成今天有效。必须把 LOGDATE 作为 where 条件传入,且不能依赖 PHP date() 在模型里动态生成——控制器要显式算好当天日期(如 date('Y-m-d'))再传进去。
-
LOGDATE字段类型建议为DATE,不是DATETIME或VARCHAR,避免隐式转换出错 - 模型中必须用
$this->db->where('LOGDATE', $date),不能写成LIKE '%2026-04-20%' - 推荐用
count_all_results()而非get()->num_rows(),前者不拉数据,性能更好
save() 方法要加「先查后插」防御逻辑
默认的 insert() 不检查唯一性,用户狂点签到按钮就可能存多条同日记录。必须在插入前查一遍是否存在:
- 查条件必须是
V_ID + LOGDATE组合,STATUS 不参与判断(因为新签到 STATUS 是 0,但已有记录可能已签退) - 查完返回 0 才执行
insert(),否则直接返回FALSE - 更彻底的做法是在数据库加唯一索引:
ALTER TABLE attendance ADD UNIQUE KEY uk_vid_logdate (V_ID, LOGDATE);
update() 更新签退时得精准定位最新一条未签退记录
用户可能上午签到后忘记签退,下午又点了一次签到(触发新记录),这时签退操作不能随便更新任意一条 STATUS = 0 的记录。
- 必须加
$this->db->order_by('ID', 'DESC')(假设 ID 自增) - 必须同时限定
LOGDATE和STATUS = 0,否则跨天签退会误改历史记录 - 如果业务允许当日多次签到(如午休打卡),那需要额外字段区分类型,不能只靠 STATUS
最易被忽略的是:前端按钮没防抖、没置灰、没禁用,导致用户一次点击发出多个请求。后端逻辑再严密,也扛不住并发插入。别只盯着模型改,前后端得一起控。











