yield生成器是php5.5之后出现的,yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。
yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组。
对比:
function gettime($num) {
$data=[];
for($i=0;$i<$num;$i++) {
$data[] = time();
}
return $data;
}
foreach (gettime(3) as $v) {
echo $v.PHP_EOL;
sleep(1);
}
//输出结果如下:
1577710522
1577710522
1577710522
使用迭代器yield:
function gettime($num) {
for($i=0;$i<$num;$i++) {
yield time();
}
}
foreach (gettime(3) as $v) {
echo $v.PHP_EOL;
sleep(1);
}
//输出结果如下
1577710705
1577710706
1577710707
对比结果发现。使用yield生成的结果是在,被外部调用时才生成。数据不是存于数组中,而是每被调用一次生成一个数据。在处理大数据是,可以明显减少内存的使用
实际的应用场景
1.读取超大文件
header("content-type:text/html;charset=utf-8");
function readTxt()
{
$handle = fopen("./test.txt", 'rb');
while (feof($handle)===false) {
yield fgets($handle);
}
fclose($handle);
}
foreach (readTxt() as $key => $value) {
# code...
echo $value.'<br />';
}
2.处理超大数据
如:求k的次方相加
k0+k1+k2+……+kn
function squares($k, $n) {
static $res=1;
for ($i=0;$i<$n;$i++){
yield $res *= $k;
}
}
$num =1;
foreach (squares(2,1000) as $v) {
$num += $v;
}
echo $num;die;
yield输出的键值对
function squares($start, $stop) {
if ($start < $stop) {
for ($i = $start; $i <= $stop; $i++) {
yield $i => $i * $i;
}
}
else {
for ($i = $start; $i >= $stop; $i--) {
yield $i => $i * $i; //迭代生成数组: 键=》值
}
}
}
foreach (squares(3, 5) as $n => $square) {
echo $n . ' squared is ' . $square .PHP_EOL;
}