PHP 8.2 类型系统实战笔记 接收参数时怎么约束function processOrder(string $id, StatusEnum $status): void { / ... / }返回值怎么表达多态语义function parseInput(string $raw): Result|Error { / ... / } $result = parseInput($input); return match(true) {$result instanceof Result => response()->json($result->data), $result instanceof Error => response()->json(['error' => $result->message], 400), }; 状态值怎么防错传【序列化】:json_encode(['status' => $orderStatus->value) → {"status":"shipped"}【反序列化】:OrderStatus::tryFrom($request->input('status')) → 成功返回实例,失败返回 null 配置对象怎么保证不可变readonly class CreateUserRequest {public function __construct( public string $name, public int $age, public ?string $email = null, ) {} }

你需要把 PHP 8.2 类型系统中零散的联合类型、交集类型、枚举、只读类等特性,整合成一份可快速查阅、能直接用于日常开发的笔记,而不是堆砌文档定义或罗列 RFC 编号。
按语义场景归类,不按语言特性罗列
先打开一个空白 Markdown 文件,标题写「PHP 8.2 类型系统实战笔记」。
第一级目录用业务动词开头:「接收参数时怎么约束」「返回值怎么表达多态语义」「状态值怎么防错传」「配置对象怎么保证不可变」——每个标题对应一个真实函数/方法的上下文,不是「联合类型」「枚举」这种语法名词。
删掉所有“PHP 8.2 引入了……”这类介绍性句子。每条笔记必须带可运行代码片段,且该片段能直接粘贴进 Laravel 控制器或 DTO 类里执行。
立即学习“PHP免费学习笔记(深入)”;
枚举序列化:只记两行核心操作
在「状态值怎么防错传」章节下,只保留这两行:
【序列化】:json_encode(['status' => $orderStatus->value) → 输出 {"status":"shipped"},不是空对象 {}。
【反序列化】:OrderStatus::tryFrom($request->input('status')) → 成功返回枚举实例,失败返回 null,绝不抛异常。
删掉所有关于 __serialize()、backed enum、标量类型对比的说明。这些内容会出现在 IDE 的类型提示里,不需要记进笔记。
联合类型:用 match 替代 if-else 链
第一步:遇到返回值可能是 Result|Error 的函数,立刻改写签名:
function parseInput(string $raw): Result|Error { ... }
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
第二步:调用处不用 instanceof 或 is_object 判断,直接用 match:
$result = parseInput($input);
return match(true) {
$result instanceof Result => response()->json($result->data),
$result instanceof Error => response()->json(['error' => $result->message], 400),
};
这一步不能省——PHP 8.2 的 match 表达式是唯一能安全解包联合类型的结构,if-else 容易漏判,且 IDE 无法推导分支类型。
只读类:只抄构造函数和属性声明
方法一:DTO 场景直接套模板
readonly class CreateUserRequest {
public function __construct(
public string $name,
public int $age,
public ?string $email = null,
)
{}
方法二:从现有类改造时,删掉所有 setter 方法,删掉所有 $this->xxx = … 赋值语句(除了构造函数内),然后在 class 前加 readonly。
注意:【只读类不能有动态属性】,所以不要在构造函数外使用 $this->newField = 'xxx',否则报致命错误。
交集类型:只在接口组合时用
当你需要一个对象既可被 JSON 序列化,又可被缓存键生成器处理,才写:
function cacheAndSerialize(JsonSerializable&Cacheable $obj): string { ... }
其他任何地方都不要出现 & 符号。交集类型不是“多个类型随便拼”,它只解决「同时满足多个契约」这一种问题,别拿它替代联合类型或泛型。


















