PHP 8.5.0 Released!

Generator::rewind

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

Generator::rewind将生成器重置到第一个 yield 位置

说明

public Generator::rewind(): void

该方法将生成器重置到第一个 yield 的位置。若调用此方法时生成器尚未到达第一个 yield 表达式,会先执行至第一个 yield 表达式,再进行重置。若生成器已处于第二个 yield 的起始位置,则会抛出 Exception

注意:

这是开始 foreach 循环时调用的第一个方法,不会在 foreach 循环结束后执行。

参数

此函数没有参数。

返回值

没有返回值。

示例

示例 #1 Generator::rewind() 示例

<?php

function generator(): Generator
{
echo
"I'm a generator!\n";

for (
$i = 1; $i <= 3; $i++) {
yield
$i;
}
}

// 初始化生成器
$generator = generator();

// 将生成器重置到第一个 yield 表达式的起始位置(如果尚未处于该位置)
$generator->rewind(); // I'm a generator!

// 此处无任何操作;生成器已处于重置状态
$generator->rewind(); // 没有输出(NULL)

// 会将生成器重置到第一个 yield 表达式(如果尚未处于该位置),并对其进行遍历
foreach ($generator as $value) {
// 在生成第一个值后,生成器会停留在第一个 yield 表达式处,直到恢复执行并继续前进到下一个 yield
echo $value, PHP_EOL; // 1

break;
}

// 恢复执行后再次重置,不会产生错误,因为生成器尚未越过第一个 yield
$generator->rewind();

echo
$generator->current(), PHP_EOL; // 1

// 不会产生错误,生成器仍处于第一个 yield 处
$generator->rewind();

// 此操作将生成器推进至第二个 yield 表达式
$generator->next();

try {
// 此操作会抛出异常,因为生成器已推进至第二个 yield
$generator->rewind(); // Fatal error: Uncaught Exception: Cannot rewind a generator that was already run
} catch (Exception $e) {
echo
$e->getMessage();
}

?>

以上示例会输出:

I'm a generator!
1
1
Cannot rewind a generator that was already run

添加备注

用户贡献的备注 1 note

up
22
i&#39;m pati on stackoverflow
9 years ago
Actually, this method can be useful to test a generator before iterating, as it executes your function up to the first yield statement. I.e. if you try to read a non-existent file in a generator, an error will normally occur only in client code foreach()'s first iteration. Sometimes this can be critical to check beforehand.

Take a look at a modified example from here:
http://php.net/manual/ru/language.generators.overview.php#112985

<?php

function getLines($file) {
$f = fopen($file, 'r');
try {
while (
$line = fgets($f)) {
yield
$line;
}
} finally {
fclose($f);
}
}

$getLines = getLines('no_such_file.txt');
$getLines->rewind(); // with ->rewind(), a file read error will be thrown here and a log file will not be cleared

openAndClearLogFile();

foreach (
$getLines as $n => $line) { // without ->rewind(), the script will die here and your log file will be cleared
writeToLogFile('reading: ' . $line . "\n");
}

closeLogFile();

?>

P.S.: When you iterate over a generator after ->rewind(), you'll get the first yielded value immediately, as the preceding code was already executed.
To Top