Edit report at https://bugs.php.net/bug.php?id=62810&edit=1
ID: 62810
Comment by: burke dot cates at gmail dot com
Reported by: burke dot cates at gmail dot com
Summary: IteratorIterator changes the class of the inner
iterator, breaking some calls
Status: Open
Type: Bug
Package: SPL related
Operating System: Linux
PHP Version: 5.4.5
Block user comment: N
Private report: N
New Comment:
I forgot the password for this bug, so I can't close it. I just tested with php
5.4.6 and this problem seems to have been fixed. I'm guessing it was part of
either bug #62629 or bug #62616
Previous Comments:
------------------------------------------------------------------------
[2012-08-13 15:57:26] burke dot cates at gmail dot com
Description:
------------
in case the test script is unreadable, https://gist.github.com/3341836 .
I have a class, A, that implements SeekableIterator, Countable in my codebase
that defines all the required methods (count(), next(), seek(), valid(),
current(), key()). When I have an instance of this class, $a, and construct a
new IteratorIterator-extending class, B with instance $b, by passing in $a to
B's constructor, a call to $b->count(), for example, will fail if A::count() is
defined to use any fields also defined in A.
An example is shown in my test script by simply extending ArrayIterator for
the
sake of simplicity. I override its count() method to echo the $extra field. The
"Notice" line in the output shows that PHP is attempting to find $extra in B
($b), but it is not there since B is defined as an extension of
IteratorIterator. This only happens when calls are going through the
IteratorIterator, as a var_dump($b->getInnerIterator()) show that the
innerIterator is the proper class.
I tried to figure out why this is happening on my own, so I started looking
through the spl_iterators.c code to figure out why this is happening. I ended
up
at Line 1534[1], which shows the ce of the inner getting set to the ce of the
object being initialized.
[1] spl_iterators.c, line 1534 :
https://github.com/php/php-src/blob/master/ext/spl/spl_iterators.c#L1534
Test script:
---------------
class A extends ArrayIterator {
private $extra;
public function __construct($extra) {
$this->extra = $extra;
parent::__construct(array(1,2,3,4,5));
}
public function count() {
var_dump($this);
echo "extra: {$this->extra}\n";
return 5;
}
}
class b extends IteratorIterator {
}
$a = new A("not gonna see this");
$b = new B($a);
echo "A: ";
$a->count();
echo "\n\nB: ";
$b->count();
Expected result:
----------------
A: object(A)#1 (2) {
["extra":"A":private]=>
string(18) "not gonna see this"
["storage":"ArrayIterator":private]=>
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
}
extra: not gonna see this
B: object(b)#2 (0) {
*not really sure what this should look like*
}
extra: not gonna see this
Actual result:
--------------
A: object(A)#1 (2) {
["extra":"A":private]=>
string(18) "not gonna see this"
["storage":"ArrayIterator":private]=>
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
}
extra: not gonna see this
B: object(b)#2 (0) {
}
Notice: Undefined property: b::$extra in /root/blankdir/test.php on line 12
extra:
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=62810&edit=1