(int)字符串转换按“从左找合法十进制整数”规则解析,遇非法字符即停;intval($str,10)显式指定十进制更安全;filter_var(...,filter_validate_int)则严格校验全字符串是否为纯整数。

PHP (int) 强制转换遇到字符串时到底怎么算
它不是简单截取数字,而是按“从左开始找合法整数部分”规则解析,遇到非法字符就停。比如 "123abc" 变成 123,但 "abc123" 直接是 0 —— 因为开头没数字,连一个有效位都找不到。
常见错误现象:(int)"0x1A" 得 0(不是 26),(int)"1e3" 得 1(不是 1000),(int)" 42 " 得 42(空格被忽略)。
- 只认十进制开头的数字,不识别十六进制(
0x...)、科学计数法(1e3)、八进制(0123)写法 - 允许开头有空白,但中间断掉就截断,比如
"12 34"→12 - 遇到
+或-会当作符号处理,"-5xyz"→-5,但"+-5"→0(符号混乱)
用 intval() 时为什么指定 base 参数反而更危险
很多人以为加个 base=10 就能“强制十进制”,其实它只是告诉 PHP “按这个进制去解析字符串开头”,而默认行为本来就是 base=10;真正危险的是你传了 base=0 或忘了设,PHP 会自动识别前缀:"0x1A" → 26,"0123" → 83(八进制),"123" → 123。
-
intval("0123")在base=0(默认)下是83,不是123 -
intval("0123", 10)才是安全的123,但必须显式写全参数 -
base超出 2–36 范围会返回0,且无警告
filter_var($str, FILTER_VALIDATE_INT) 和类型转换根本不是一回事
它不做“尽力解析”,而是做“全字符串校验”:整个字符串必须是纯整数(可带正负号),不能有多余字符,也不能是空格包裹的。失败直接返回 false,不是 0 —— 这点和 (int) 完全相反。
立即学习“PHP免费学习笔记(深入)”;
-
filter_var("123", FILTER_VALIDATE_INT)→123 -
filter_var("123abc", FILTER_VALIDATE_INT)→false(不是123) -
filter_var(" 123 ", FILTER_VALIDATE_INT)→false(开头/结尾空格不允许) - 想兼容空格?得先
trim(),再校验
字符串转 int 最稳的组合写法
没有银弹,但可以分场景控制风险。核心原则:明确意图,拒绝隐式行为。
- 要“严格整数输入”(如 ID、分页页码)→ 先
trim(),再filter_var(..., FILTER_VALIDATE_INT) !== false - 要“宽松提取数字开头”且确定格式可控(如日志里抠编号)→ 用
intval($str, 10),显式写死10 - 要兼容前后空格 + 防止意外前缀(如用户粘贴了带空格或换行的数字)→
intval(trim($str), 10) - 永远别在关键逻辑里用
(int)$str处理不可信输入,它太安静、太宽容、太容易掩盖问题
最常被忽略的点:开发时用的测试数据往往“刚好能过”,比如 "123",但线上可能混入 "123px"、"-123.45"、"0x7F",而 (int) 全部默默吞掉异常部分,结果错得毫无痕迹。











