简体   繁体   English

RecursiveIteratorIterator和嵌套的RecursiveArrayIterators

[英]RecursiveIteratorIterator and nested RecursiveArrayIterators

I've been messing with RecursiveArrayIterators for handling nested objects as trees. 我一直在使用RecursiveArrayIterators将嵌套对象作为树来处理。 The following code is bothering me as the result is returning only some of the values I'm expecting. 下面的代码困扰我,因为结果仅返回我期望的某些值。 Mainly, the root node seems to never be iterated over. 主要地,根节点似乎永远不会被迭代。 I have a feeling I've just been staring at it a bit too long but wanted to make sure I was on the right track with this. 我觉得我只是盯着它看了太久,但是想确保自己在正确的轨道上。

class Container extends \RecursiveArrayIterator
{
    protected $_alias;

    public function __construct( $alias = null )
    {
        if( is_null( $alias ) )
        {
            $alias = uniqid( 'block_' );
        }

        $this->_alias = $alias;
    }

    public function getAlias()
    {
        return $this->_alias;
    }
}

try
{
    $root = new Container( 'root_level' );
    $block = new Container( 'first_level' );
    $child = new Container( 'second_level' );
    $child_of_child_a = new Container( 'third_level_a' );
    $child_of_child_b = new Container( 'third_level_b' );

    $child->append( $child_of_child_a );
    $child->append( $child_of_child_b );
    $child_of_child_a->append( new Container );
    $child_of_child_a->append( new Container );
    $block->append( $child );
    $root->append( $block );

    $storage = new \RecursiveIteratorIterator( $root, RecursiveIteratorIterator::SELF_FIRST );

    foreach( $storage as $key => $value )
    {
        print_r( str_repeat( ' ', $storage->getDepth() * 4 ) . $value->getAlias() . PHP_EOL );
    }
}
catch( \Exception $e )
{
    var_dump( $e->getMessage() );
}

With the result being... 结果是...

first_level
second_level
    third_level_a
        block_51f98b779c107
        block_51f98b779c124
    third_level_b

Where's the root node? 根节点在哪里?

ANSWER 回答

Sven's answer jarred my over-worked brain into processing this correctly. Sven的回答使我过度劳累的大脑无法正确处理。 This was my final bit of successful code in case someone else is attempting something similar. 这是我成功代码的最后一点,以防其他人尝试类似的事情。

class OuterContainer extends \ArrayIterator
{

}

class Container extends \ArrayIterator
{
    protected $_alias;

    public function __construct( $alias = null )
    {
        if( is_null( $alias ) )
        {
            $alias = uniqid( 'container_' );
        }

        $this->_alias = $alias;
    }

    public function getAlias()
    {
        return $this->_alias;
    }
}

try
{
    $c1 = new Container( 'Base' );

    $c1_c1 = new Container( 'Base > 1st Child' );

    $c1_c2 = new Container( 'Base > 2nd Child' );

    $c1_c1_c1 = new Container( 'Base > 1st Child > 1st Child' );

    $c1_c1->append( $c1_c1_c1 );

    $c1->append( $c1_c1 );

    $c1->append( $c1_c2 );

    $outer_container = new OuterContainer;

    $outer_container->append( $c1 );

    $storage = new \RecursiveIteratorIterator( new \RecursiveArrayIterator( $outer_container ), RecursiveIteratorIterator::SELF_FIRST );

    foreach( $storage as $key => $value )
    {
        print_r( $value->getAlias() . PHP_EOL );
    }
}
catch( \Exception $e )
{
    var_dump( $e->getMessage() );
}

The root node is not there because you are not using the RecursiveArrayIterator correctly. 根节点不存在,因为您没有正确使用RecursiveArrayIterator。

It's intended use is to have an array with multiple sub-arrays in any level and structure, and give this array into ONE instance of the RecursiveArrayIterator, and to iterate over everything, put this into a RecursiveIteratorIterator. 它的预期用途是使一个数组具有任意级别和结构的多个子数组,并将该数组放入RecursiveArrayIterator的一个实例中,并遍历所有内容,并将其放入RecursiveIteratorIterator中。

That way, the entire array, including it's top level, will be iterated. 这样,整个数组(包括顶层)都将被迭代。

Because you abused the RecursiveArrayIterator to be the carrier of information, the top level object is not iterated. 因为您滥用了RecursiveArrayIterator作为信息的载体,所以不会迭代顶层对象。

Suggested easy example that has some nastyness, but demonstrates the principle: 建议的简单示例有些讨厌,但演示了原理:

$root = array( 'root_level' );
$block = array( 'first_level' );
$child = array( 'second_level' );
$child_of_child_a = array( 'third_level_a' );
$child_of_child_b = array( 'third_level_b' );

$child[] = $child_of_child_a;
$child[] = $child_of_child_b ;
$child_of_child_a[] = array('');
$child_of_child_a[] = array('');
$block[] = $child;
$root[] = $block ;

$storage = new \RecursiveIteratorIterator( new \RecursiveArrayIterator($root), RecursiveIteratorIterator::SELF_FIRST );

var_dump($root);
foreach ($storage as $key=>$value) {
    echo $key.": ".$value."\n";
}

Result output: 结果输出:

array(2) {
    [0] =>
  string(10) "root_level"
  [1] =>
  array(2) {
        [0] =>
    string(11) "first_level"
    [1] =>
    array(3) {
            [0] =>
      string(12) "second_level"
      [1] =>
      array(1) {
                ...
            }
      [2] =>
      array(1) {
                ...
            }
    }
  }
}
0: root_level
1: Array
    0: first_level
1: Array
    0: second_level
1: Array
    0: third_level_a
2: Array
    0: third_level_b

It's output is not quite the same, but my point is that you can iterate over the structure without having every single node to be an instance of the RecursiveArrayIterator. 它的输出并不完全相同,但是我的观点是,您可以遍历结构,而不必让每个节点都成为RecursiveArrayIterator的实例。 You can add anything that is either an array, or an object acting as an array, or an object that can usefully be iterated. 您可以添加任何内容,既可以是数组,也可以添加充当数组的对象,或者可以进行有效迭代的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM