array_is_list() 判断数组是否为连续整数键列表以确保 JSON 序列化为数组;交集类型(如 LoggerInterface & Serializable)强制多重接口契约;Fiber::suspend()/resume() 用于可控协程流转,三者均只断言不修复,需先明确稳定契约再使用。

PHP 8.1 的几个关键函数和类型特性不是“锦上添花”,而是直接堵住老项目里高频出错的缺口——比如状态值乱传、API 返回结构不可控、对象契约模糊。用对了,能省掉大量运行时 if 校验和注释猜意图;用错了,反而让类型系统形同虚设。
array_is_list() 判断数组是否该被序列化为 JSON 数组
这个函数解决的是一个隐蔽但高频的问题:为什么 json_encode() 有时输出 [1,2,3],有时却输出 {"0":1,"1":2,"2":3}?根源不在数据内容,而在数组键的“合法性”。
- 它只认一种结构:键必须是
0, 1, 2, ..., n-1的连续整数,缺一不可,顺序不能乱 - 哪怕你只是
unset($arr[0])再array_values($arr),也得确保重索引后没漏掉中间值 - 在 API 响应层,建议在
json_encode()前加一层判断:if (!array_is_list($data)) { throw new InvalidArgumentException('Expected list for array response'); },避免前端解析失败 - 注意:空数组
[]是 list,但[1=>'a', 2=>'b']不是,哪怕键是数字也不行
交集类型(LoggerInterface & Serializable)强制多重契约
交集类型不是语法糖,它是把“这个对象既要记日志又要能序列化”这种业务要求,从注释和文档里搬到类型声明里,让 IDE 和 PHP 自己去拦错。
- 只能用于类或接口,不能写
string & int或array & Countable,否则解析失败 - 常见误用是混用联合类型:
(A & B) | C不合法,得拆成两个函数或用泛型+条件类型绕开 - 在依赖注入中特别有用:比如一个服务注册时要求
Cacheable & Flushable & Configurable,容器就能在构建阶段报错,而不是等第一次调用才崩 - 属性声明也支持:
private LoggerInterface & Serializable $handler;,但要注意构造时必须传入满足全部接口的实例
Fiber::suspend() 和 resume() 控制协程流转时机
别把它当成“轻量线程”来用。Fiber 的核心价值是把异步回调链拉直,但前提是 suspend/resume 的配对必须严格、可预测。
立即学习“PHP免费学习笔记(深入)”;
-
Fiber::suspend()只能在 Fiber 内部调用,外部调用会 fatal error;而$fiber->resume()必须在start()之后、且 Fiber 处于 suspended 状态时才能调用 - 常见陷阱:在
try/catch外围 resume 一个已抛出异常的 Fiber,会导致未捕获异常直接终止进程 - 实际适合场景很窄:比如封装一个需要分步确认的支付流程,每步之间挂起等待用户操作回调,而不是用来替代
sleep()或模拟并发 - 不要在 Fiber 中做阻塞 IO(如
file_get_contents()),它不会自动 yield,得配合事件循环或显式suspend()
最易被忽略的一点:交集类型和 array_is_list() 都不提供运行时“修复”能力——它们只做断言。如果业务逻辑本身允许稀疏数组或动态接口组合,硬套这些特性反而增加维护成本。先厘清契约是否真的稳定,再决定是否上类型锁。



















