PHP 7将(int)浮点数转换改为“四舍五入到最近偶数”,而PHP 5为截断;溢出时PHP 7静默归零,PHP 5可能返回边界值或负值;JSON大整数需用JSON_BIGINT_AS_STRING避免隐式转换差异。

PHP 5 和 PHP 7 中 (int) 强制转换对浮点数的处理逻辑不同
最典型的差异出现在将接近整数边界的浮点数转为整型时。PHP 5 使用“截断(truncation)”,而 PHP 7 改为“四舍五入到最近整数(round half to even)”,但仅限于浮点数到整型的强制转换场景。
例如:var_dump((int) 2.9); 在两者中都输出 2;但 (int) 2.5 在 PHP 5 是 2(直接截掉小数),在 PHP 7 是 2(偶数规则),而 (int) 3.5 在 PHP 5 是 3,PHP 7 是 4。
- 这个行为变化只影响
(int)、intval()(默认 base 10 且无$base参数时) -
floor()、ceil()、round()不受影响,它们的行为跨版本一致 - 若浮点数超出
PHP_INT_MAX或低于PHP_INT_MIN,PHP 7 会静默转为0(或边界值),PHP 5 可能返回负溢出结果(如-1),不可依赖
大整数字符串转 int 时溢出表现不一致
当字符串表示的数字超过平台整型范围(如 64 位系统上大于 9223372036854775807),PHP 5 和 PHP 7 都不会报错,但返回值不同:
var_dump((int) "9223372036854775808");
立即学习“PHP免费学习笔记(深入)”;
- PHP 5.6(64 位):返回
9223372036854775807(即PHP_INT_MAX) - PHP 7.0+:返回
0(明确归零,更可预测) - 注意:
intval("9223372036854775808")行为同(int),但filter_var($str, FILTER_VALIDATE_INT)在超界时直接返回false,推荐用于校验
PHP_INT_MAX 值本身在 32 位/64 位环境下的实际边界必须实测
别只查文档——PHP_INT_MAX 不是固定常量,它取决于编译时目标架构。同一份代码在 Docker 的 alpine(musl + 32 位模拟)和 Ubuntu 20.04(glibc + 64 位)里可能得到完全不同的整型上限。
- 运行
php -r "echo PHP_INT_MAX . \"\\n\";"查当前环境真实值 - 用
PHP_INT_SIZE === 8判断是否为 64 位整型支持,而非检查 PHP 版本 - 涉及 ID、时间戳、金额计算时,若可能接近
2^31-1(约 21 亿)或2^63-1(约 9.2e18),务必加运行时断言:assert($val = PHP_INT_MIN);
从数组键或 JSON 解码中隐式生成整型时的兼容性陷阱
JSON 中的超大整数(如 {"id": 9223372036854775808})被 json_decode() 解析后,在 PHP 5 中变成 float,在 PHP 7 中默认仍是 float(除非启用 JSON_BIGINT_AS_STRING)。但当你把它当作数组键使用:$arr[(int)$json->id] = true;,就触发了前述转换差异。
- 解决方案不是升级 PHP,而是统一用字符串做键:
$arr[strval($json->id)] = true; - 或解码时强制大整数为字符串:
json_decode($json_str, false, 512, JSON_BIGINT_AS_STRING) - 用
is_int()检查变量类型时,注意它对 float 类型返回false,哪怕该 float 看起来像整数(如is_int(123.0)是false)
边界值从来不是“理论上超了才出问题”,而是“刚好卡在 PHP_INT_MAX ±1 时,PHP 5 和 PHP 7 给你两个不同答案,而你的 if 分支只写了其中一个”。实测比文档可靠,var_dump() 比注释可信。











