Edit report at https://bugs.php.net/bug.php?id=63823&edit=1
ID: 63823 Updated by: s...@php.net Reported by: s...@php.net Summary: SPL InfiniteIterator needs explicit rewind to be usable in a closure Status: Open Type: Bug Package: SPL related Operating System: Linux PHP Version: 5.4Git-2012-12-21 (Git) Block user comment: N Private report: N New Comment: A bigger example is: <?php echo "'foreach' on ArrayIterator\n"; $c = array('one', 'two', 'three'); $c_it = new ArrayIterator($c); foreach ($c_it as $key => $val) { var_dump($val); } echo "\n'foreach' on InfiniteIterator\n"; $a = array('one', 'two', 'three'); $a_it = new InfiniteIterator(new ArrayIterator($a)); $i = 0; foreach ($a_it as $key => $val) { if ($i++ >= 7) break; var_dump($val); } echo "\n'for' on ArrayIterator\n"; $d = array('one', 'two', 'three'); $d_it = new ArrayIterator($d); for ($i = 0; $i < 3; $i++) { var_dump($d_it->current()); $d_it->next(); } echo "\n'for' on InfiniteIterator\n"; $b = array('one', 'two', 'three'); $b_it = new InfiniteIterator(new ArrayIterator($b)); for ($i = 0; $i < 7; $i++) { var_dump($b_it->current()); $b_it->next(); } ?> This outputs: 'foreach' on ArrayIterator string(3) "one" string(3) "two" string(5) "three" 'foreach' on InfiniteIterator string(3) "one" string(3) "two" string(5) "three" string(3) "one" string(3) "two" string(5) "three" string(3) "one" 'for' on ArrayIterator string(3) "one" string(3) "two" string(5) "three" 'for' on InfiniteIterator NULL string(3) "two" string(5) "three" string(3) "one" string(3) "two" string(5) "three" string(3) "one" So the odd behavior is with the last loop. A "real" life script (from discussion on php.internals) is: <?php // Replacing words in a string with a sequential, repeating set of replacement words $replacements = array('one', 'two', 'three'); $replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements)); $replacements_iterator->rewind(); // why is the rewind needed? $result = preg_replace_callback( '/word/', function($matches) use ($replacements_iterator) { $r = $replacements_iterator->current(); $replacements_iterator->next(); return $r; }, 'word word word word word' ); var_dump($result); // Outputs: // string(21) "one two three one two" // Without the call to $replacements_iterator->rewind(), the output is: // string(18) " two three one two" ?> Previous Comments: ------------------------------------------------------------------------ [2012-12-21 02:17:17] s...@php.net Description: ------------ SPL's InfiniteIterator returns NULL for the first access, unless used in a 'foreach' loop, or a rewind is done. This means that an explicit rewind is needed before an InfiniteIterator can be safely be used in an application. Test script: --------------- <?php $b = array('one', 'two', 'three'); $b_it = new InfiniteIterator(new ArrayIterator($b)); for ($i = 0; $i < 7; $i++) { var_dump($b_it->current()); $b_it->next(); } ?> Expected result: ---------------- string(3) "one" string(3) "two" string(5) "three" string(3) "one" string(3) "two" string(5) "three" string(3) "one" Actual result: -------------- NULL string(3) "two" string(5) "three" string(3) "one" string(3) "two" string(5) "three" string(3) "one" ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=63823&edit=1