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

Reply via email to