php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62810 IteratorIterator changes the class of the inner iterator, breaking some calls
Submitted: 2012-08-13 15:57 UTC Modified: 2012-08-30 22:51 UTC
From: burke dot cates at gmail dot com Assigned: tyrael (profile)
Status: Closed Package: SPL related
PHP Version: 5.4.5 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: burke dot cates at gmail dot com
New email:
PHP Version: OS:

 

 [2012-08-13 15:57 UTC] 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: 


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-08-17 16:16 UTC] burke dot cates at gmail dot com
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
 [2012-08-30 22:51 UTC] tyrael@php.net
closing it on the request of burke.
 [2012-08-30 22:51 UTC] tyrael@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: tyrael
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 05 04:01:35 2025 UTC