PHP 8.1中联合类型本身不因null触发TypeError,前提是显式包含null(如string|null);否则传null给string|int等不含null的联合类型或内置函数(如array_merge)会报TypeError。

PHP 8.1 中,联合类型本身**不会因为传入 null 而直接触发 TypeError**——前提是该联合类型**已显式包含 null**(如 string|null)。真正触发错误的,是把 null 传给一个**未声明可空**的联合类型参数(例如只写了 string|int),或传给**不接受 null 的内置函数**(如 array_merge())。
确认是否真由联合类型校验引发
先区分错误来源:
-
联合类型参数报错:函数签名写的是
function foo(string|int $x),却传了null→ 触发TypeError: Argument #1 ($x) must be of type string|int, null given -
内置函数报错:如
array_merge($a, $b)中$a是null→ PHP 8.1+ 报TypeError: array_merge(): Argument #1 must be of type array, null given(这和联合类型无关,但常被误认为“联合类型问题”)
兼容旧代码的三类处理方式
针对函数参数联合类型拒绝 null 的场景,按优先级推荐:
-
升级声明:显式加入
|null把string|int改为string|int|null,让类型契约明确允许空值。这是最直接、最符合 PHP 8+ 类型语义的做法。 -
保持签名不变:前置判空并提供默认值
在函数体内用
if ($x === null)分支处理,或统一转为安全默认值(如空字符串、0)。注意:不能靠运行时自动转换,必须显式控制流程。 -
降级兼容(不推荐):临时关闭严格模式
移除
declare(strict_types=1);可让部分弱类型转换“静默发生”,但会丧失类型安全,且无法解决array_merge等函数的报错,仅作紧急兜底。
特别注意 ThinkPHP 等框架的典型陷阱
很多旧项目在 ThinkPHP 6.0.13 或更早版本中,存在类似逻辑:
立即学习“PHP免费学习笔记(深入)”;
$where = $request->param('where'); // 可能为 null
$data = array_merge($default, $where); // PHP 8.1+ 此处直接 TypeError
修复不是改联合类型,而是补判空:
- 所有传给
array_merge的变量加?? []:array_merge($default, $where ?? []) - 查询条件拼接前统一初始化:
$where = $request->param('where') ?: []; - 升级到 ThinkPHP 6.0.14+,核心已修复部分位置,但自定义逻辑仍需自查。
为什么不能依赖 ?string 简写
?string 在 PHP 8.0+ 仍有效,等价于 string|null,但它**仅支持单类型可空**。若你需要 int|string|null,就必须写全联合类型,?int|string 是语法错误。所以旧代码若混用 ?Type 和多类型逻辑,升级后务必展开为显式联合类型。



















