Union Types 与 Mixed 类型分别在什么版本引入?使用场景?
解读
国内一线、二线互联网公司的 PHP 面试中,类型系统演进是“必问”考点。Union Types 与 Mixed 是 PHP8 时代最具代表性的新类型,面试官通过这两个点同时考察:
- 候选人对版本迭代的敏感度(能否快速说出 8.0 与 8.2)
- 对类型安全、接口设计、向下兼容的实际落地经验
- 是否具备“旧项目渐进升级”的思路,而不仅是“追新”
答不上版本号=基础不牢;说不出场景=没写过业务代码;两者都模糊=直接降档。
知识点
-
Union Types(联合类型)
- 引入版本:PHP 8.0(2020-11-26 GA)
- 语法:T1|T2|…|Tn,最多支持 2^16 种组合
- 运行时:依旧严格类型声明模式 declare(strict_types=1) 生效;弱类型模式自动强制转换失败抛 TypeError
- 典型场景: – 返回值“多态”:缓存接口 get(string identity) – 替代“假泛型”:before 用 @param 注解,now 用 User|Collection 明确提示 IDE 与静态分析工具
-
Mixed 类型
- 引入版本:PHP 8.2(2022-12-08 GA)
- 语义:top type,等价于 union(string|int|float|bool|array|object|resource|null)
- 与“省略类型”区别:显式 mixed 会强制检查,省略类型不会
- 典型场景: – 数据总线层:消息队列 payload、RPC 结果体,结构完全由上游决定 – 高阶函数:array_map 回调、中间件洋葱模型,参数类型无法提前约束 – 逐步重构:先把“历史遗留”标为 mixed,再分阶段细化,避免一次性大爆炸
-
版本对比记忆口诀 “8.0 联合打基础,8.2 混合收万物”——国内面试官普遍接受这种顺口溜式回答,既显专业又带节奏。
答案
Union Types 于 PHP 8.0 引入,用于在参数、返回值、属性中声明“多种可能类型”的显式约束,解决旧版只能混合使用 @param 注解导致的静态分析盲区,典型场景包括缓存层多态返回值、兼容对象与标量的遗留接口。Mixed 类型则到 PHP 8.2 才正式落地,是 PHP 类型系统的顶级类型,用来显式表达“可以是任何类型”的宽松契约,常见于消息队列 payload、中间件回调、不可预测结构的第三方数据等场景,同时方便团队以“先标 mixed 后细化”的策略完成渐进式重构。
拓展思考
- 向下兼容策略:线上大量 7.4 代码无法一步到位升级 8.x,可先用 Psalm/PHPStan baseline 把“隐式 mixed”扫出来,再按模块升级到 8.0 加 Union,最后 8.2 统一改 mixed,实现“灰度类型化”。
- 性能角度:Union 与 mixed 均会在 OPCache 里生成额外的 type_info 掩码,压测显示 5% 以内损耗,高并发接口若极限优化可先用单类型 + 断言兜底,再回退到联合类型。
- 与即将落地的 JIT 增强(PHP 8.3+)结合:mixed 参数因为类型未知,JIT 无法内联缓存,建议热路径函数仍优先细化类型;Union 类型在 8.3 已支持 JIT 快速路径,可放心使用。
- 面试加分项:主动提到“国内某电商大促网关项目,把 200+ 遗留接口先用 mixed 标注,再按流量优先级逐步拆成 Union,最后单类型,整体重构周期 3 个月,线上零回滚”,可瞬间把“背书”变成“实战”。