根本原因是类型转换未真正落地——隐式转换、返回值丢失、对象/资源序列化破坏原始类型导致转换失效。

PHP转换后类型不对,根本原因不是转换没发生,而是你没真正“转换成功”——多数情况是用了隐式转换、漏了返回值、或对象/资源被序列化破坏了原始类型。
为什么 (int) 转完还是字符串?
常见于从 $_GET 或数据库读出的值:虽然写了 (int)$id,但没赋值给变量或没用在后续逻辑里。
- 错误写法:
(int)$_GET['id'];—— 转换结果被丢弃,$_GET['id']本身仍是字符串 - 正确写法:
$id = (int)$_GET['id'];或$id = intval($_GET['id']); - 注意:
intval("123abc")返回123,但intval("abc123")返回0,别依赖它做安全校验
is_int() 返回 false,但明明用了 (int)
这通常发生在数组键、JSON 解析或 MongoDB ObjectId 场景中——类型看似“转了”,实则被中间层悄悄还原或封装。
- 数组键自动转整型:
$arr = ["1" => "a", 1 => "b"];→ 实际只有1 => "b",字符串键"1"被当成整数键覆盖 - JSON 解析默认把数字当
float或int,但若启用了JSON_BIGINT_AS_STRING,大整数会变成字符串,(int)强转可能溢出或截断 - MongoDB 中误将
MongoDB\BSON\ObjectId实例json_encode()或转数组,结果变成["oid" => "xxx"],再怎么(string)也变不回 ObjectId 对象
严格模式下 TypeError 却没报错?
因为 declare(strict_types=1); 只作用于**同一文件内声明的函数**,不影响内置函数(如 strlen())、第三方扩展或未声明类型提示的函数。
立即学习“PHP免费学习笔记(深入)”;
- 写了
function foo(int $x) { }但没加declare(strict_types=1);→ 仍会隐式转换 - 加了
declare(strict_types=1);但调用的是array_map()这类内置函数 → 不受约束 - 对象属性类型声明(PHP 7.4+)只在校验赋值时触发,
$obj->id = "123";若public int $id;,才会抛TypeError
最常被忽略的一点:类型检查和类型转换是两件事。用 is_int() 确认类型,不等于你已经完成了安全转换;而 (int) 只是表达式,不落地就等于没做。尤其在处理外部输入、序列化数据、ORM 封装层时,原始类型极易在某一层被“悄悄抹平”。



















