生成器是php 5.5+的语言结构,非内置函数,yield函数返回generator对象,实现iterator接口,可直接foreach遍历;手动控制需调用current()、next()等方法;慎用iterator_to_array()避免内存暴增;php 7.0+支持return值通过getreturn()获取。

PHP 5.5+ 的生成器(Generator)本身不是“内置函数”,而是一种语言结构,通过 yield 关键字定义的函数会自动返回一个 Generator 对象——它实现了 Iterator 接口,因此可直接用于 foreach、for 配合 ->next() 等标准迭代方式,无需额外“内置函数”驱动。
直接用 foreach 遍历最自然
这是最常用、最推荐的方式。生成器对象天然支持 foreach,PHP 自动调用其内部的 current()、next()、valid() 等方法:
- 每次进入循环体前,自动生成下一个值并赋给变量
- 函数在
yield处暂停,状态(如局部变量、执行位置)完整保留 - 下一次迭代时从中断点继续,不重跑整个逻辑
示例:
function readLargeFile($file) {
$handle = fopen($file, 'r');
while (($line = fgets($handle)) !== false) {
yield rtrim($line);
}
fclose($handle);
}
// 直接 foreach,内存恒定
foreach (readLargeFile('/var/log/big.log') as $line) {
if (str_contains($line, 'ERROR')) {
echo $line . "\n";
}
}
手动控制用 Generator 对象方法
当需要精细控制(比如跳过、提前终止、检查状态),可显式调用 Generator 实例的方法:
-
->current():获取当前产出的值(尚未调用next()时为null) -
->key():获取当前键(若yield 'key' => $val,否则为整数索引) -
->next():推进到下一个yield或结束 -
->valid():判断是否还有有效值(未结束) -
->rewind():仅对未开始或已结束的生成器有效;多数生成器不支持重置
适用场景:流式处理中需条件跳过、分页拉取、或与协程调度配合。
配合数组函数需先转为数组(慎用)
像 array_map、array_filter 这类函数不接受生成器,必须先用 iterator_to_array() 转换:
- 这会**立刻消耗全部生成值并存入内存**,彻底失去生成器的内存优势
- 仅适用于小规模数据,或你明确知道结果集很小
-
大数据场景应改用
foreach+ 手动逻辑替代
错误示范(破坏内存优化):
$gen = generateRange(1, 1000000); $filtered = array_filter(iterator_to_array($gen), fn($x) => $x % 2 === 0); // ❌ 加载百万项进内存
PHP 7.0+ 可获取 return 值补充元信息
若生成器末尾有 return $finalValue,可在遍历结束后用 ->getReturn() 获取终结状态:
- 必须确保生成器已完全执行(即
->valid() === false) - 常用于返回统计数、成功标记、错误摘要等非主体数据
- 不影响迭代过程,也不参与
foreach输出
示例:
function processLogs($file) {
$count = 0;
foreach (readLargeFile($file) as $line) {
if (str_contains($line, 'WARN')) {
$count++;
yield $line;
}
}
return ['processed' => $count, 'source' => $file];
}
$gen = processLogs('/tmp/app.log');
foreach ($gen as $warning) {
echo $warning . "\n";
}
var_dump($gen->getReturn()); // ['processed' => 42, 'source' => '/tmp/app.log']php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











