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
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ralph at smashlabs dot com
New email:
PHP Version: OS:

 

 [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: Fri Apr 19 11:01:28 2024 UTC