PHP中int与float是底层完全独立的类型,存储、比较、数组键匹配、JSON处理等行为均不同,布尔值也是独立类型,易因隐式转换出错;安全类型判断需用filter_var等函数而非is_int。
整数和浮点数在 PHP 里不是“能算就行”,而是存储和比较逻辑完全不同
PHP 的
和
在底层是两种独立类型,即使你写
和
,它们的类型、内存布局、哈希值、甚至数组键匹配行为都可能不一致。这不是 PHP “松散”带来的错觉,而是真实差异。
常见错误现象:
–
返回
(因为键是 float,而数组里存的是 int)
–
输出
,但
是
–
只保留一个键(JSON 键强制转为字符串,
冲突)
整数用补码二进制直接存数值,精确、无舍入;浮点数走 IEEE 754(PHP 默认双精度),
是必然结果,不是 bug
PHP 不会自动把
转成
去当数组键用——除非你显式调用
或
,否则类型就卡死在那里
性能上,整数运算快、可被 OPcache 更好优化;浮点数涉及指数对齐、尾数归一化,还可能触发 FPU 指令路径,尤其在循环中累积误差+性能损耗更明显
布尔值在 PHP 里根本不是“真假数字”,它是个独立的 type,但又最容易被隐式转换坑
PHP 的
类型只有两个值:
和
,它既不是整数 1/0,也不是字符串 "1"/"",但在松散比较(
)时会被强制转成其他类型——这正是大多数混淆的源头。
常见错误现象:
–
成立(空数组被当成
)
–
是
(字符串 "0" 是唯一被判定为 false 的非空字符串)
–
得到
(key 被转成字符串)
立即学习
“
PHP免费学习笔记(深入)
”;
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
判断真假请用严格比较:
或
;避免用
或
判布尔
函数返回布尔值时,别直接拿去算术运算:
看似省事,但
是
时加的是 1,是
时加的是 0 —— 这依赖隐式转换,可读性差且易出错
数据库字段映射要注意:MySQL 的 TINYINT(1) 常被 PDO 当作
返回,不是
;想得到布尔得手动配置
并启用
,或自己 cast
怎么安全地做类型判断和转换?别信
就万事大吉
只检查运行时类型,不关心值是否“看起来像整数”。比如
是
,但
也是
——因为
是 float,哪怕它数学上等于整数。
使用场景:
– 接口参数校验要区分“必须是整数”还是“可以是数字字符串”
– JSON 解析后所有数字默认是 float,哪怕原始是
(PHP 8.2+ 有
但没数字类型保留选项)
判断“是否可无损转为整数”:用
,它能处理字符串
、
,但拒绝
、
强制转整数优先用
,但注意截断不四舍五入;需要四舍五入请用
从 float 安全转 int:先用
排除 INF/NAN,再用
判断是否为整数值,最后
转换
PHP 8.0+ 的联合类型和属性类型声明,让区别不再“靠猜”
过去靠文档或注释说明“这个参数应该是 int”,现在可以直接写
。但这不是万能胶——联合类型只约束输入输出,不改变底层行为。
容易踩的坑:
–
传入
没问题,但返回值仍是 float,类型声明不覆盖运行时计算逻辑
– 属性声明
在构造后仍可能被外部赋值为 float,除非配合
拦截或启用严格模式
开启
是前提,否则类型声明只在调用处校验,不阻止内部 float 混入
数组元素类型无法用联合类型直接约束(
是无效语法),得用
+ PHPDoc 或 PHPStan/psalm 静态分析补位
JSON 解析仍是最大漏网之鱼:无论你怎么声明
,
返回的
字段永远是 float —— 因为 JSON 规范没有整数/浮点数区分
类型之间的边界在 PHP 里从来不是模糊的,只是松散比较和隐式转换掩盖了它。真正难的不是记住“int 是整数、float 是小数”,而是理解什么时候该拦住 float、什么时候该接受它、以及为什么
和
对同一个数值给出不同答案。
intfloat55.0array_key_exists(5.0, [5 => 'ok'])falsevar_dump(0 == 0.0)bool(true)var_dump(0 === 0.0)bool(false)json_encode([5 => 'a', 5.0 => 'b'])"5"0.1 + 0.2 !== 0.3floatint(int)intval()booltruefalse==if ([] == false)falsevar_dump((bool)"0")bool(false)json_encode([true => 'yes', false => 'no']){"1":"yes","":"no"}=== true=== false== 1== 0$count += $found$foundtruefalseintboolPDO::ATTR_EMULATE_PREPARES => falsePDO::MYSQL_ATTR_DIRECT_QUERYis_int($x)is_int()is_int("123")falseis_int(123.0)false123.0123JSON_INVALID_UTF8_IGNOREfilter_var($x, FILTER_VALIDATE_INT) !== false"123""-456""12.3""abc"(int)round($x, 0, PHP_ROUND_HALF_DOWN)is_finite($x)floor($x) === $x(int)$xfunction foo(int|float $x): voidfunction bar(int $x): void { echo $x + 0.5; }3public int $count = 0;__set()declare(strict_types=1);arrayarrayarray{score: int}json_decode($json, true)scorejson_encode()array_key_exists()