生成器
PHP 有一个很好的机制,可以以紧凑的方式创建迭代器。这种迭代器有一些严重的限制:它们只能向前,不能倒转。事实上,即使只是从头开始启动一个迭代器,也必须重建生成器。从本质上说,这是一种只能向前的迭代器。
使用 yield
关键字而不是 return
关键字的函数。它的作用与返回语句相同,但不会停止函数的执行。生成器函数可以任意多次产生数据。
在数组中填充值时,这些值必须存储在内存中,这可能会导致超出 PHP 内存限制或生成器需要大量的处理时间。如果将逻辑放在生成器函数中,则不存在这种开销。生成器函数可以根据需要生成任意数量的结果,而不需要先预置一个数组。
下面是一个简单的生成器,它将 var_dump
一个字符串,说明生成器已启动。然后,函数将生成前五个平方数,同时用 var_dump
输出它们在数列中的位置。最后,它将指示生成器已结束:
<?php
function squaredNumbers()
{
var_dump("Generator starts.");
for ($i = 0; $i < 5; ++$i) {
var_dump($i . " in series.");
yield pow($i, 2);
}
var_dump("Generator ends.");
}
foreach (squaredNumbers() as $number) {
var_dump($number);
}
该脚本的第二部分循环该函数并对每个数字运行 var_dump
字符串。其输出如下:

让我们稍微修改一下这个函数。
非常需要注意的是,如果给变量添加返回类型,则只能声明 Generator
、Iterator
或 Traversable
、integer
的返回类型。
下面是代码:
<?php
function squaredNumbers(int $start, int $end): Generator
{
for ($i = $start; $i <= $end; ++$i) {
yield pow($i, 2);
}
}
foreach (squaredNumbers(1, 5) as $number) {
var_dump($number);
}
结果如下:

如果我们想要生成一个键和一个值怎么办? 嗯,这相当容易。
对于那些在 PHP 5 中使用过生成器的人来说,关于生成器还有一些事情需要提及:在 PHP 5 中,当您想要在将变量设置为变量的同时同时生成变量时,必须将 yield
语句括在括号中。 PHP 7 中不存在此限制。
这适用于 PHP 5 和 7:
$data = (yield $value);
这仅适用于 PHP 7:
$data = yield $value;
假设我们想要修改生成器,以便它产生键值结果。代码如下所示:
Unresolved include directive in modules/ROOT/pages/ch05/ch5-04.adoc - include::example$/Chapter 5/Generator/index.php[]
当我们测试这个时,我们将 var_dump
一个二维数组,其中包含生成器在给定迭代中生成的任何键值存储。
下面是输出:

还有一些其他提示,没有变量的 Yield 语句(如后续命令中所示)将简单地产生 null
:
yield;
您还可以使用 yield from
来生成任何给定生成器的内部值。
假设我们有一个包含两个值的数组:
[1, 2]
当我们使用 yield from
产生一个包含两个值的数组时,我们得到了数组的内部值。 让我演示一下:
<?php
function innerGenerator()
{
yield from [1, 2];
}
foreach (innerGenerator() as $number) {
var_dump($number);
}
这将显示以下输出:

但是,现在让我们更改此脚本,以便它使用 yield
而不是 yield from
:
<?php
function innerGenerator()
{
yield [1, 2];
}
foreach (innerGenerator() as $number) {
var_dump($number);
}
现在我们将看到,我们不仅获得了数组的内部值,还获得了外部容器:
