PHP账单编号自动生成功能新年失效问题求助
问题根源
问题出在字符串排序逻辑上:
账单号是字符串类型,执行ORDER BY patientno DESC时,数据库会按字符ASCII值排序。2023年12月的账单号(如L5-1223-9999)中,12的首字符1比2024年1月账单号01的首字符0大,因此字符串排序后,2023年12月的编号始终排在2024年1月编号前面。
每次生成新编号时,取到的lastid都是2023年12月的最大编号,此时判断substr($lastid, $CIcnt + 1, 2) != $month(即12 != 01)成立,就会触发新序列分支生成0001,循环往复导致序列号无法递增。
修复方案
最可靠的解决方式是仅查询当前年月对应的账单号,确保拿到当月的最大序列号,而非历史所有编号的最大值。修改后的代码如下:
$CI = "L5"; //Example only $CIcnt = strlen($CI); $offset = $CIcnt + 6; // 获取当前年月的两位字符串 $month = date("m"); // e.g. 09 $year = date("y"); // e.g. 23 $currentYearMonth = "$month$year"; // 修改查询:只查当前年月的账单号,取最新的一条 $query = "SELECT patientno FROM iap2 WHERE patientno LIKE ? ORDER BY patientno DESC LIMIT 1"; // 用预处理语句避免SQL注入 $stmt = mysqli_prepare($con, $query); $likePattern = "$CI-$currentYearMonth-%"; mysqli_stmt_bind_param($stmt, "s", $likePattern); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); $row = mysqli_fetch_assoc($result); $lastid = $row['patientno'] ?? null; // 判断是否需要开启新序列 if(empty($lastid)) { $number = "$CI-$month$year-0001"; } else { // 递增序列号 $idd = substr($lastid, $offset); $id = str_pad((int)$idd + 1, 4, 0, STR_PAD_LEFT); $number = "$CI-$month$year-$id"; }
额外优化说明
- 显式强制类型转换:给
$idd加上(int),避免字符串转整数的潜在问题,逻辑更严谨。 - 预处理语句:避免SQL注入风险,尤其当
$CI可能来自用户输入时。 - 空值处理:用
?? null确保无数据时$lastid为null,避免未定义索引警告。
内容的提问来源于stack exchange,提问作者Student
相关产品推荐
相关产品推荐

