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

Reply via email to