Rewindable PHP Generators

Today I was refactoring some code in one of my libraries, and ended up replacing a named Iterator class with a Generator. To my surprise this changed behaviour, which I noticed due to a broken test. A test verifying that I could iterate multiple times through the iterator – good that I did write that! And so I found out that you can not actually rewind a Generator. By extension, you can also iterate through the iterator only once. If you try to rewind or iterate multiple times, you’ll get an Exception. Gah!

$generator = $myGeneratorFunction();
iterator_to_array($generator);
iterator_to_array($generator); // boom!
$generator = $myGeneratorFunction();
$generator->next();
$generator->rewind(); // boom!

Luckily, this is trivial to get around. Just make an Iterator that recreates the Generator on rewind and delegates to it. I’ve created a (extremely) little library that holds such an adapter, so I can tackle this problem without cluttering my other libraries with such a random infrastructure concern. Which of course you can use as well if you want.

$generator = new RewindableGenerator( $myGeneratorFunction );
iterator_to_array($generator);
iterator_to_array($generator); // works as expected
$generator->rewind(); // works as expected

The library is called Rewindable Generator. You can install it with Composer using the package name jeroen/rewindable-generator.

Jeroen De Dauw is founder and CEO of Professional Wiki and builds NeoWiki. More about me. Reply by email or on Mastodon, Bluesky or X.

One comment on “Rewindable PHP Generators”

Comments are closed.