php中$_get参数默认为字符串,直接使用易引发类型错误、sql注入或警告;应先用filter_var校验并转换,再处理键存在性与默认值。

PHP中$_GET参数默认是字符串,直接用会出问题
PHP的$_GET数组里所有值都是字符串类型,哪怕URL里写的是?id=123,$_GET['id']也是"123"(带引号的字符串)。直接拿它去查数据库、做数学运算或类型敏感判断(比如=== 123),八成会踩坑。
常见错误现象:
– if ($_GET['page'] === 1) { ... } 永远不进分支
– MySQL查询WHERE id = $_GET['id']触发隐式类型转换,可能被绕过注入检测
– 传入array_shift()等函数时抛Warning: array_shift() expects parameter 1 to be array(因为把字符串当数组用了)
- 永远别信
$_GET的类型,显式转换是底线 - 用
(int)强制转换最常用,但要注意截断行为:比如(int)"123abc"得123,(int)"abc123"得0 - 如果要严格校验“纯数字”,优先用
filter_var($val, FILTER_VALIDATE_INT),它对"123abc"或" 123 "都返回false
用filter_var校验并转换整型更安全
filter_var不是简单转类型,而是带语义的验证——它能区分“这是个合法整数”和“这看起来像整数但混了别的东西”。尤其适合处理用户输入的ID、分页页码、状态码这类必须精确的场景。
使用场景:
– 接口要求?limit=20且不允许负数或超大值
– 管理后台URL里?user_id=5000必须确保是正整数
– 防止?sort=-1被恶意用于SQL注入(配合后续白名单)
立即学习“PHP免费学习笔记(深入)”;
-
filter_var($_GET['id'], FILTER_VALIDATE_INT):只验证,合法返回int,非法返回false -
filter_var($_GET['page'], FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 1000]]):加范围限制,超出即false - 注意
filter_var对空字符串""、null、未定义键都返回false,别忘了判空
intval()和(int)的区别与陷阱
三者都能“转整数”,但行为差异明显:(int)和intval()是强制转换,filter_var是验证后转换。选错就等于主动放行脏数据。
-
(int)"123abc"→123;(int)"abc123"→0;(int)""→0(容易把空参当0处理) -
intval("123abc")→123;intval("abc123")→0;但intval("")也返回0,和(int)一样不可靠 -
intval("0xff", 16)支持进制转换,(int)不支持;但日常处理URL参数几乎用不到这个特性 - 性能上三者差距可忽略,别为这点速度牺牲安全性
别漏掉键存在性检查和默认值处理
很多新手只盯着“怎么转整型”,却忘了$_GET['id']可能根本不存在——这时filter_var($_GET['id'], ...)会触发Notice: Undefined index,而(int)$_GET['id']会警告Undefined variable。
- 先用
isset($_GET['id'])或array_key_exists('id', $_GET)兜底 - 更简洁写法:
$id = filter_var($_GET['id'] ?? '', FILTER_VALIDATE_INT) ?: 1;(?? ''防未定义,?: 1设默认值) - 如果业务允许缺失参数(比如搜索页
?q=php没带page),默认值必须明确,别依赖(int)"" === 0这种隐式逻辑
真正麻烦的从来不是“怎么转”,而是“转之前有没有确认它存在、是否在合理范围内、缺了怎么办”。这些边界情况一漏,线上就容易出500或查到不该查的数据。











