|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49104 AppendIterator::append($iterator) calls $iterator->rewind() with no reason
Submitted: 2009-07-29 22:54 UTC Modified: 2017-10-24 07:26 UTC
Avg. Score:4.4 ± 0.8
Reproduced:14 of 14 (100.0%)
Same Version:5 (35.7%)
Same OS:5 (35.7%)
From: seva dot lapsha at gmail dot com Assigned:
Status: Open Package: SPL related
PHP Version: 5.3.0 OS: *
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2009-07-29 22:54 UTC] seva dot lapsha at gmail dot com
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:
class ArrayIterator1 extends ArrayIterator {
	function rewind() {
		echo ".";

$i1 = new ArrayIterator1(array(1, 2, 3));
$i2 = new ArrayIterator1(array(4, 5, 6));

$i = new AppendIterator();

foreach ($i as $n) {
	echo $n;

Expected result:

rewind() of each append()ed iterator should be called on demand when iterating and not when append()ing.

Actual result:

On each append() each append()ed iterator's rewind is called with no need.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2009-07-29 22:57 UTC] 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:)
 [2011-03-23 18:32 UTC] demjan at kaluzki dot de
The rewind is invoked only on the first appended (not empty) inner-iterator. 


$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();
unset($workaround[0]); // no further append calls are allowed, 
                       // otherwise it seems to hang up in infinite loop
 [2013-09-09 08:49 UTC] hanskrentel at yahoo dot de
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 -

In code:

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:

$i1 = new ArrayIterator1(array(1, 2, 3));
$i2 = new ArrayIterator1(array(4, 5, 6));

$append = new AppendIterator();
/* @var $i ArrayIterator */
$i = $append->getArrayIterator();

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 
- ArrayAccess can be used, too: $i[] = $i1;

I hope this helps someone running into the issue in PHP user land.
 [2017-10-24 07:26 UTC]
-Status: Assigned +Status: Open -Assigned To: colder +Assigned To:
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu May 30 07:01:30 2024 UTC