Generators 提供了一种内存高效的方式来迭代大型数据集,通过使用 yield 关键字一次一个(延迟地)生成值,而不是一次性在内存中构建整个数组。它们非常适合大型或流式数据。
yield 对比返回数组
php
{
= [];
( = ; < ; ++) { [] = ; }
;
}
{
( = ; < ; ++) {
;
}
}
(() ) {
();
}
Generators 提供了一种内存高效的方式来迭代大型数据集,通过使用 yield 关键字一次一个(延迟地)生成值,而不是一次性在内存中构建整个数组。它们非常适合大型或流式数据。
{
= [];
( = ; < ; ++) { [] = ; }
;
}
{
( = ; < ; ++) {
;
}
}
(() ) {
();
}
yield 使函数成为生成器:它延迟地生成值,每次迭代一个,并在迭代之间保持其状态——因此无论生成多少个值,内存使用量都保持恒定。
function readLines(string $file): Generator {
$handle = fopen($file, 'r');
while (($line = fgets($handle)) !== false) {
yield $line; // yield one line at a time — never load the whole file
}
fclose($handle);
}
foreach (readLines('huge-10gb.csv') as $line) { // processes a 10GB file with tiny memory
process($line);
}
使用生成器逐行读取一个巨大文件使用恒定内存——使用 file()(将整个文件加载到数组中)是不可能的。
function fetchRows(PDOStatement $stmt): Generator {
while ($row = $stmt->fetch()) {
yield $row['id'] => $row; // yield key => value, streaming DB rows
}
}
生成器非常适合流式传输数据库结果——一次处理一行,而不是将整个庞大的结果集加载到内存中。
生成器是一个重要的 PHP 功能,用于大型数据集的内存高效处理——理解它们对于构建能够大规模处理数据而不会耗尽内存的应用程序非常有价值。
它们解决的核心问题是,构建大数据的完整数组(数百万条记录、巨大文件的行、大型数据库结果集)会消耗巨大的内存并导致应用程序崩溃,而生成器延迟地一次一个生成值,使内存使用量保持恒定,无论数据集大小如何。
最有影响力的用例是实用且常见的:逐行读取大文件(用微小内存处理多 GB 的 CSV 或日志,使用加载所有内容的函数是不可能的)、流式传输数据库结果(逐行处理大型查询结果),以及处理大型甚至无限序列。
理解 yield、延迟评估以及何时使用生成器(任何时候你会在内存中构建大数组时),可以让你编写可扩展的数据处理代码,能够优雅地处理大容量——这是批处理作业、导入/导出、报表生成和数据管道中的常见实际需求。
虽然对于小数据集不需要,但生成器是内存敏感的 PHP 的必备知识,它处理大量数据,将能够构建可扩展数据处理代码的开发人员与那些应用在大工作量下失败或变慢的开发人员区分开来,使其成为对性能敏感、数据密集型 PHP 应用程序的宝贵高级知识。