php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48166 RecursiveIteratorIterator does not persist state parent in getChildren()
Submitted: 2009-05-06 15:58 UTC Modified: 2009-05-07 00:38 UTC
From: ralph at smashlabs dot com Assigned: colder (profile)
Status: Wont fix Package: SPL related
PHP Version: 5.2.9 OS: *
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
43 - 12 = ?
Subscribe to this entry?

 
 [2009-05-06 15:58 UTC] ralph at smashlabs dot com
Description:
------------
Currently, its difficult to extend RecursiveFilterIterator() with additional __construct() arguments (for configuring its behavior).  The reason its difficult is b/c when getChildren() is called, a new instance of the RFI is created (only way you'd know this is if you look into the source of RFI).

Workaround currently is this (But is not generic enough to all use cases):

replace getChildren():

    function getChildren()
    {
        if (empty($this->ref)) {
            $this->ref = new ReflectionClass($this);
        }
        return $this->ref->newInstance($this->getInnerIterator()->getChildren(), $this->_otherArgs);
    }

Reproduce code:
---------------
$rArray = array('a' => array('ab', 'ac', 'ad' => array('ada', 'adc')), 'b' => array('bb', 'bc'));

$ri = new RecursiveArrayIterator($rArray);
$filter = new MyRFI($ri, 'argument');
$iterator = new RecursiveIteratorIterator($filter);

foreach ($iterator as $key => $item) {
    echo $key . ' - ' . $item . PHP_EOL;
}

class MyRFI extends RecursiveFilterIterator
{
    protected $_otherArg = null;

    public function __construct($iterator, $otherArg = null)
    {
        $this->_otherArg = $otherArg;
        parent::__construct($iterator);
    }

    public function accept()
    {
        echo ($this->_otherArg) ? 'Arg Present' : 'Arg NOT Present';
        echo PHP_EOL;
        return true;
    }
}

Expected result:
----------------
Arg Present
Arg Present
0 - ab
Arg Present
1 - ac
Arg Present
Arg Present
0 - ada
Arg Present
1 - adc
Arg Present
Arg Present
0 - bb
Arg Present
1 - bc 

Actual result:
--------------
Arg Present
Arg NOT Present
0 - ab
Arg NOT Present
1 - ac
Arg NOT Present
Arg NOT Present
0 - ada
Arg NOT Present
1 - adc
Arg Present
Arg NOT Present
0 - bb
Arg NOT Present
1 - bc


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-05-07 00:38 UTC] colder@php.net
Sorry for the false hope, it is indeed how it's supposed to work and not a bug. Since the new iterator is instanciated directly inside getChildren, you can't magically have new arguments to your constructor and have them filled appropriately.

But you can basically implement all features you want by simply overriding getChildren. 

Clone + setiterator could also work, but changing that would introduce BC breaks, and I'm not sure it would make more sense than what we have now.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 20 03:01:28 2024 UTC