php 8联合类型需用string|int等非空类型组合或?string语法,禁用string|null或mixed|array;应优先选联合类型而非mixed以提升类型安全与ide支持。

PHP 8 的联合类型怎么写才不报错
PHP 8 引入了联合类型(Union Types),但不是所有写法都合法——比如 mixed 不能和其它类型并列,null 必须用问号语法(?string)而不是写进联合里。常见错误是直接写 function foo(string|null $x) {},这在 PHP 8.0+ 会报 ParseError: Union types cannot contain nullable types。
-
string|int✅ 合法:两个非空具体类型 -
?string✅ 合法:等价于string|null,但语法更简洁且被明确支持 -
string|null❌ 报错:PHP 8 禁止在联合中显式写null -
mixed|array❌ 报错:mixed是“顶层类型”,不能参与联合
什么时候该用联合类型,而不是 mixed
联合类型不是为了“更宽松”,而是为了“更精确的宽松”——它告诉 IDE 和静态分析器:这个参数只可能是这几个类型之一,不是任意值。比如处理 API 返回数据时,后端可能返回 int(成功 ID)或 string(错误消息),这时 int|string 比 mixed 更安全、可推导性更强。
- 用
int|string:能触发 IDE 参数提示、类型推导、严格模式下避免误赋值 - 用
mixed:完全放弃类型约束,foo($x)传个stdClass也不会报错,但后续调用$x->id就崩了 - 注意:联合类型仍不支持泛型细化(如
array<int>|array<string></string></int>不等于array),实际要收窄还得靠运行时is_int()或match分支
match 表达式配合联合类型做类型分发
联合类型本身不自动分支逻辑,但和 PHP 8 的 match 配合,能写出比 if-elseif 更清晰的类型处理逻辑。尤其适合参数为 string|int|float 这类“标量多态”场景。
function formatValue(string|int|float $input): string {
return match (true) {
is_string($input) => strtoupper($input),
is_int($input) => "ID-{$input}",
is_float($input) => number_format($input, 2),
default => throw new TypeError("Unexpected type: " . gettype($input)),
};
}
-
match不做类型隐式转换(1 === '1'为 false),比switch更可靠 - 必须覆盖所有联合类型分支,否则
default是必需的(哪怕你认为“不可能”) - 如果联合类型含
bool,注意is_bool()要单独判断——因为1和0可能被is_int()拦截,true/false才走is_bool()
联合类型 + 默认值的坑:null 怎么设
带默认值的联合参数,最容易踩的坑是把 null 当成一个可选分支来写。正确方式只有两种:
立即学习“PHP免费学习笔记(深入)”;
- 用可空语法:
function bar(?string $s = null) {}—— 这是string|null的标准写法 - 用联合 + 显式默认:
function bar(string|int $x = 0) {},但此时null传入会直接报错,不能混用 - 错误示范:
function bar(string|int|null $x = null) {}→ 解析失败 - 如果真需要“三选一且允许 null”,只能退回到
mixed并手动校验,或者拆成两个参数(如$value+$type_hint)
联合类型不是万能胶,它收紧的是声明边界,而不是放宽运行时行为。写的时候多看一眼错误信息里的 “Union types cannot contain…” 提示,基本就能避开八成问题。











