Loop a RecursiveIteratorIterator from an extended RecursiveIterator with extra arguments

StackOverflow https://stackoverflow.com/questions/9197726

  •  27-04-2021
  •  | 
  •  

Question

Let's say I have following ArrayObject:

$array_object = new ArrayObject(array(
   array('1', '2', '3', '4'),
   array('3', '6', '7', '8'),
   array('9', '3', '11', '12'),
));

And I extend RecursiveFilterIterator to accept only children elements which value is equal to some value passed in an argument:

class myRecursiveFilterIterator extends RecursiveFilterIterator
{
   public $value;

   public function __construct($it, $value)
   {
      parent::__construct($it);
      $this->value = $value;
   }

   public function accept()
   {
      return (parent::hasChildren()) || (parent::current() == $this->value);
   }
}

I create an instance of this brand new iterator, to filter values equal than 3:

$recursive_filter_iterator = new myRecursiveFilterIterator(new RecursiveArrayIterator($array_object), 3);

If now I loop the whole myRecursiveFilterIterator using an RecursiveIteratorIterator:

foreach (new RecursiveIteratorIterator($recursive_filter_iterator) as $value) {
   var_dump($value);
}

I get following warning:

Warning: Missing argument 2 for myRecursiveFilterIterator::__construct() in /my/path/test.php on line myLine Notice: Undefined variable: value in /my/path/test.php on line myOtherLine

So it'is like when looping RecursiveIteratorIterator is trying to instance myRecursiveFilterIterator without passing second argument $value.

This doesn't happen if I extend FilterIterator without supplying extra arguments.

Was it helpful?

Solution

I decided to run the script my self and this is what have noticed

  1. you are working with multi array so parent::current() can be an array that means that the line below is wrong because $this->value is an integer.

    return (parent::hasChildren()) || (parent::current() == $this->value);
    
  2. $this->current () also switches String to Array you can do this to manage both depending on what you want to achieve

    if (is_array ( $current )) {
        return ($this->hasChildren ()) || (in_array ( ( string ) $this->value, $this->current () ));
    } else {
    
        //var_dump ( $this->value, $this->current () );
    
        return ($this->hasChildren ()) || ( $this->value == $this->current ());
    }
    
  3. You also need to implement getChildren method that is why PHP was complaining about Missing argument 2 for myRecursiveFilterIterator::__construct()

    public function getChildren() {
        return new self ( $this->getInnerIterator ()->getChildren (), $this->value );
    }
    

============================== DISCARD OLD RESPONSE =============================

PHP most have communicated a wrong error message .. your code fine but the error originated when you tried to use foreach with RecursiveIteratorIterator directly

Here is a better approach using RecursiveArrayIterator to encapsulate RecursiveIteratorIterator :

foreach (new RecursiveArrayIterator(new RecursiveIteratorIterator($recursive_filter_iterator)) as $value) {
    var_dump($value);
} 

:)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top