Цикл RecursiveIteratorIterator из расширенного RecursiveIterator с дополнительными аргументами - PullRequest
2 голосов
/ 08 февраля 2012

Допустим, у меня есть следующее ArrayObject:

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

И я расширяю RecursiveFilterIterator, чтобы принимать только дочерние элементы, значение которых равно некоторому значению, переданному в аргументе:

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);
   }
}

Я создаю экземпляр этого совершенно нового итератора, чтобы отфильтровать значения, равные 3:

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

Если сейчас я зациклю все myRecursiveFilterIterator, используя RecursiveIteratorIterator:

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

Я получаю следующее предупреждение:

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

То есть, когда цикл RecursiveIteratorIterator пытается создать экземпляр myRecursiveFilterIterator без передачи второго аргумента $value.

Это нене произойдет, если я расширю FilterIterator без предоставления дополнительных аргументов.

1 Ответ

2 голосов
/ 17 марта 2012

Я решил запустить скрипт сам, и это то, что заметил

  1. вы работаете с несколькими массивами, поэтому parent::current() может быть массивом, что означает, что строка ниже неверна, потому что $this->value является целым числом.

    return (parent::hasChildren()) || (parent::current() == $this->value);
    
  2. $this->current () также переключает String на Array, вы можете сделать это для управления обоими в зависимости от того, чего вы хотите достичь

    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. Вам также необходимо реализовать метод getChildren, поэтому PHP жаловался на отсутствие аргумента 2 для myRecursiveFilterIterator::__construct()

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

============================== ОТКЛОНИТЬ СТАРЫЙ ОТВЕТ ============== ===============

В большинстве PHP сообщалось о неправильном сообщении об ошибке .. Ваш код в порядке, но ошибка возникла, когда вы пытались использовать foreach напрямую с RecursiveIteratorIterator

Вот лучший подход с использованием RecursiveArrayIterator для инкапсуляции RecursiveIteratorIterator:

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

:)

...