PHP实现登录次数统计时多次登录后Login_Times不递增问题
问题根因
- 核心流程缺失:代码中的SELECT查询从未被实际执行。仅将SQL字符串赋值给
$GetLoginTimes,未调用mysqli_query()将查询发送到数据库获取结果集,就直接把字符串传入mysqli_fetch_array()。此时函数因接收的参数不是合法结果集返回NULL,NULL参与+1运算的结果固定为1,因此无论用户第几次登录,计算出的新登录次数永远是1,更新操作只会反复把字段值设置为1,无法完成递增。这也对应了你观察到的现象:首次登录时因为字段初始值一般为0,被代码赋值为1看起来符合预期,后续登录时永远被赋值为1,就不会出现数值递增。 - 取值逻辑错误:即便SELECT查询被正常执行,
mysqli_fetch_array()返回的是关联/索引数组类型的结果行,不是直接的字段标量值,直接对数组执行加法运算会触发PHP语法警告,且数组强制转换为数值的结果固定为1,同样会导致计算结果恒定。 - 额外隐患:先查再更新的逻辑在高并发场景下,会因多个请求同时读取到相同的旧值,导致登录次数统计不准;同时直接拼接用户输入的邮箱字段到SQL语句中,存在SQL注入风险。
修复方案
推荐实现方式
无需单独查询当前登录次数,直接利用数据库的原子自增操作完成更新,单条SQL即可覆盖需求,同时解决上述代码bug和并发计数不准的问题:
// 使用预处理语句绑定参数,避免SQL注入,执行原子自增更新 $stmt = $con->prepare("UPDATE usertable SET Login_Times = Login_Times + 1 WHERE email = ?"); $stmt->bind_param("s", $email); $stmt->execute();
如果业务逻辑需要读取更新后的登录次数,可在自增执行完成后再单独查询,无需沿用“先查值、计算新值、再更新”的三段式逻辑。
兼容原有逻辑的修正写法(不推荐)
如果必须保留原有流程,需要补全缺失的查询执行步骤、修正取值方式、做好参数转义:
// 1. 执行SELECT查询获取结果集 $getTimesSql = "SELECT Login_Times FROM usertable WHERE email = ?"; $stmt = $con->prepare($getTimesSql); $stmt->bind_param("s", $email); $stmt->execute(); $result = $stmt->get_result(); $userRow = $result->fetch_assoc(); // 2. 从返回的数组中取出真实字段值参与运算 $newLoginTimes = $userRow['Login_Times'] + 1; // 3. 执行更新操作 $updateSql = "UPDATE usertable SET Login_Times = ? WHERE email = ?"; $stmt2 = $con->prepare($updateSql); $stmt2->bind_param("is", $newLoginTimes, $email); $stmt2->execute();
注意:这种写法在多请求并发场景下,很容易因多个请求同时读取到相同的旧登录次数,导致计数更新偏差,优先选择数据库原子自增的实现方式。
内容的提问来源于stack exchange,提问作者Bebo
相关产品推荐
相关产品推荐

