PHP 8.1交集类型是编译期类型声明机制,仅允许在函数参数、返回值和类属性中使用&连接对象类型,禁止标量、联合类型或双类组合,错误直接触发ParseError。

PHP 8.1 的交集类型(Intersection Types)不是“调用”出来的,它不参与运行时行为,也不提供任何函数或方法供你主动调用。它是编译期的类型声明机制,只在函数签名、属性声明等位置起约束作用——写对了,PHP 解析器就接受;写错了,直接报 ParseError,根本跑不起来。
交集类型只能出现在三处声明位置
你不能在变量赋值、foreach、match 或局部作用域里“使用”交集类型,它只在以下地方合法:
- 函数或方法的参数类型声明,例如:
function handle(Loggable & Serializable $obj) - 函数或方法的返回类型声明,例如:
function getWriter(): Writable & Flushable - 类属性声明(PHP 8.1+),例如:
private LoggerInterface & JsonSerializable $logger;
像 $x: ArrayAccess & Countable = $data; 这种写法会立刻触发 ParseError: Syntax error —— PHP 不支持变量类型标注交集类型。
交集类型不是运行时检查,而是解析期契约
它不依赖 instanceof 或反射做判断,而是在 PHP 解析 .php 文件生成 opcode 时就验证是否可能满足。这意味着:
立即学习“PHP免费学习笔记(深入)”;
- 如果两个接口有同名方法但签名冲突(比如参数类型不兼容),会直接报
ParseError,而非等到调用时才失败 - IDE(如 PHPStorm)能据此推断出完整方法列表,补全
$obj->log()和$obj->serialize()两者 - 静态分析工具(PHPStan/ Psalm)能基于此做更精确的路径推导
例如:Iterator & Countable 合法,因为 Iterator extends Traversable,且两者方法无冲突;但 JsonSerializable & ArrayAccess 若都定义了 jsonSerialize(): mixed 和 offsetGet($key): mixed 就没问题,一旦某接口改了返回类型,就可能在加载阶段崩掉。
常见非法组合与错误提示
试图绕过限制会导致明确的解析错误,而不是静默降级:
-
string & array→ParseError: Intersection types cannot contain scalar types -
MyClass & YourClass→ParseError: Intersection types cannot contain two classes(PHP 不支持多重继承) -
int & bool或void & Throwable→ 同样触发 scalar 类型禁止错误 -
LoggerInterface & (string|null)→ParseError: Union types are not allowed in intersection types(PHP 8.1 是“纯”交集,不支持混合联合)
这些都不是警告,是硬性语法拦截——没机会进 autoloader,更不会走到 __invoke 或 __call 阶段。
真正容易被忽略的是:交集类型不改变对象行为,它只是把本该靠文档、注释、测试和人肉 review 来保证的“同时实现 A 和 B”这件事,搬进了语言层。一旦你写了 A & B,就意味着所有调用点都必须传入满足两者的实例,漏一个接口,整个文件就加载失败。这不是便利功能,是契约升级——用错地方,代价比写错 union 高得多。



















