应先校验id格式合法性再查库,整型用is_numeric()与filter_var双重检查,字符串id用正则验证;存在性判断优先用select count(1)配合pdo预处理,避免sql注入与性能浪费。

查数据库前先确认ID格式是否合法
直接查库前跳过校验,容易被注入或触发无意义查询。比如传入 "1 OR 1=1" 或空字符串,可能绕过判断逻辑或报错。
- 整型ID用
is_numeric()+filter_var($id, FILTER_VALIDATE_INT)双重检查,避免八进制、科学计数法等边缘情况 - 字符串ID(如UUID)优先用正则,例如
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i - 绝不信任
$_GET['id']或$_POST['id']的原始值,哪怕只是做存在性判断
用 SELECT COUNT(1) 而不是 SELECT * 查存在性
只关心“有没有”,不关心数据内容时,SELECT COUNT(1) 比 SELECT * 或 SELECT id 更轻量——MySQL 不需要回表、不加载字段值、优化器通常走索引覆盖。
- 语句示例:
SELECT COUNT(1) FROM users WHERE id = ?,配合 PDO 预处理防止注入 - 别用
SELECT id FROM ... LIMIT 1再判!empty($row),多一次PHP层判断且没省下IO - 如果表有复合唯一索引(如
(category_id, sort_order)),WHERE 条件必须匹配最左前缀,否则可能全表扫描
注意 NULL 和 0 在 PHP 中的隐式转换陷阱
查出来是 0 还是 NULL,直接影响 if ($result) 判断结果。尤其当ID是自增主键,但误查了不存在的 0 值时,容易误判为“存在”。
- PDO 默认返回字符串,
$count === '0'是字符串,if ($count)会为 true —— 必须用(int)$count > 0或严格比较 - 用
fetchColumn()直接取数值,避免数组包装;再用=== false判断查询失败,=== '0'判断不存在 - MySQL 中
id = 0在严格模式下不会命中自增主键(除非显式插入),但业务表若允许0作为有效ID,就得单独约定并文档化
缓存层要和数据库状态一致
加 Redis 缓存后,ID存在性判断可能从“查库”变成“查缓存”,但删/改记录时若漏掉缓存清理,就会返回过期结果。
- 推荐策略:缓存 key 用
"exists:user:{$id}",设置短 TTL(如 60 秒),不永久缓存“不存在”状态 - 删除记录时,除了删数据,必须
DEL exists:user:123;更新 ID 对应数据时,也应删该 key,下次查自动回源 - 不要用
SETNX做存在性锁,它解决的是并发写问题,不是读判断
实际中最容易被忽略的是缓存穿透场景:恶意请求大量不存在的ID,导致缓存不命中、请求直打数据库。这时候光靠格式校验和SQL优化不够,得在入口加布隆过滤器或空值缓存——但那是另一层问题了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











