yield不是语法糖而是内存开关,它使百万级数据处理从爆内存变为稳如平湖,因Generator仅存当前状态、内存恒定O(1),而传统方式内存线性增长O(n)。

PHP 中的 yield 不是语法糖,而是实实在在的内存开关——它把“全量加载”变成“按需吐出”,让百万级数据处理从爆内存变成稳如平湖。
为什么 yield 能省下 90% 内存?
传统方式(比如 range(1, 1000000) 或 fetchAll())会把全部数据塞进数组,内存占用随数据量线性增长(O(n))。而 yield 函数返回的是 Generator 对象,内部只保存当前执行状态和局部变量,内存基本恒定(O(1))。
- 调用生成器函数时,代码不立即执行,只返回一个迭代器对象
- 每次
foreach取值或手动调用next(),才执行到下一个yield并暂停 - 中间状态(如循环变量、文件句柄、数据库游标)全程保留在函数作用域内
典型大数据场景落地写法
不是所有大数组都适合 yield,关键看数据是否可“流式产生”。以下是最常用且效果显著的三类:
-
读取超大文本文件:逐行
fgets()+ yield,避免file_get_contents()把整个文件拖进内存 -
遍历海量数据库结果:用 PDO 的
fetch()配合 while 循环 yield,替代fetchAll() - 聚合分页 API 全量数据:封装多页请求逻辑,在每页响应后 yield 当前批次,不缓存全部响应体
必须避开的三个高危坑
yield 本身很轻量,但一不小心就会被“拉回数组模式”,瞬间引爆内存:
立即学习“PHP免费学习笔记(深入)”;
-
禁用
iterator_to_array():哪怕加了limit参数,底层仍会尝试收集成完整数组 -
别对生成器做
json_encode()或array_values():这些函数隐式触发全量消费 -
警惕键名类型混用:写
yield 'id_1' => $val和yield 1 => $val,后者会被 PHP 强转为字符串键,可能覆盖前者
进阶技巧:yield from 与 return 的分工
PHP 7.0+ 支持 yield from 委托另一个生成器,让逻辑更清晰;同时支持 return 返回元信息——这两者严格分离,不可混淆:
-
yield from anotherGenerator():把控制权交给子生成器,键值原样透传 -
return 'done':该值不会出现在foreach中,只能通过$gen->getReturn()单独获取,适合传总数、状态码、耗时统计等上下文信息 - yield 后不要跟 return 逻辑:生成器关闭后,后续代码不再执行



















