Edit report at https://bugs.php.net/bug.php?id=49104&edit=1
ID: 49104 Comment by: hanskrentel at yahoo dot de Reported by: seva dot lapsha at gmail dot com Summary: AppendIterator::append($iterator) calls $iterator->rewind() with no reason Status: Assigned Type: Bug Package: SPL related Operating System: * PHP Version: 5.3.0 Assigned To: colder Block user comment: N Private report: N New Comment: AppendIterator just takes care that the internal iterator state is at a validated position of at least one iterator. This perhaps is not necessary at all, but it *might* be needed to take care of internal iterator states as PHP shares a lot of code across iterators (as this ticket didn't get much traction nor feedback from core developers, I'd say in summary nobody wants to fiddle with that). In the end AppendIterator is still an IteratorIterator and those have this internal state: Compare: Why must I rewind IteratorIterator - http://stackoverflow.com/q/2458955/367456 In code: http://lxr.php.net/xref/PHP_5_4/ext/spl/spl_iterators.c#3347 If rewind on appending is an issue - and despite / in contrast to what has been outlined as workaround already - if those safety checks PHP does are not wanted, you can take care your own by adding the iterators directly to the internal collection of iterators: <?php $i1 = new ArrayIterator1(array(1, 2, 3)); $i2 = new ArrayIterator1(array(4, 5, 6)); $append = new AppendIterator(); /* @var $i ArrayIterator */ $i = $append->getArrayIterator(); $i->append($i1); $i->append($i2); Some notes: - You can append anything here, no type-check is enforced. However everything not a Traversable will crash the script on iteration when reached (e.g. exit code -1073741819). This has the benefit that unlike ArrayIterator::append() you *can* add Traversable (e.g. IteratorAggregate) and not only Iterator. This also works for Traversable only classes like DatePeriod. - This still does work while iterating (as it does for AppendIterator::append()). - ArrayAccess can be used, too: $i[] = $i1; I hope this helps someone running into the issue in PHP user land. Previous Comments: ------------------------------------------------------------------------ [2011-03-23 18:32:46] demjan at kaluzki dot de The rewind is invoked only on the first appended (not empty) inner-iterator. workaround: $workaround = new ArrayIterator(array('delete_me_after_all_append_calls_are_done')); $a = new ArrayIterator(array('a', 'b')); $b = new ArrayIterator(array('c', 'd')); $append = new AppendIterator(); $append->append($workaround); // invokes implicit: // $workaround->rewind(); // $workaround->valid(); // $workaround->current(); // $workaround->key(); // $workaround->rewind(); $append->append($a); $append->append($b); unset($workaround[0]); // no further append calls are allowed, // otherwise it seems to hang up in infinite loop ------------------------------------------------------------------------ [2009-07-29 22:57:40] seva dot lapsha at gmail dot com Line 6: x This causes append to happen twice: should be read as * This causes rewind to happen twice:) ------------------------------------------------------------------------ [2009-07-29 22:54:19] seva dot lapsha at gmail dot com Description: ------------ AppendIterator::append($iterator) calls $iterator->rewind() with no reason. This causes append to happen twice: 1) when $iterator appended; 2) when $iterator starts iterating. Reproduce code: --------------- <?php class ArrayIterator1 extends ArrayIterator { function rewind() { echo "."; parent::rewind(); } } $i1 = new ArrayIterator1(array(1, 2, 3)); $i2 = new ArrayIterator1(array(4, 5, 6)); $i = new AppendIterator(); $i->append($i1); $i->append($i2); foreach ($i as $n) { echo $n; } ?> Expected result: ---------------- .123.456 rewind() of each append()ed iterator should be called on demand when iterating and not when append()ing. Actual result: -------------- ..123.456 On each append() each append()ed iterator's rewind is called with no need. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=49104&edit=1