【问题标题】:RecursiveIteratorIterator and nested RecursiveArrayIteratorsRecursiveIteratorIterator 和嵌套的 RecursiveArrayIterators
【发布时间】:2013-08-01 15:53:29
【问题描述】:

我一直在使用 RecursiveArrayIterators 将嵌套对象作为树处理。以下代码困扰着我,因为结果只返回了我期望的一些值。主要是,根节点似乎永远不会被迭代。我有一种感觉,我只是盯着它看了太久,但想确保我在正确的轨道上。

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

结果是……

first_level
second_level
    third_level_a
        block_51f98b779c107
        block_51f98b779c124
    third_level_b

根节点在哪里?

回答

Sven 的回答让我过度劳累的大脑无法正确处理这个问题。这是我最后一段成功的代码,以防其他人尝试类似的事情。

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

【问题讨论】:

    标签: php spl recursiveiterator


    【解决方案1】:

    根节点不存在是因为您没有正确使用 RecursiveArrayIterator。

    它的预期用途是在任何级别和结构中拥有一个包含多个子数组的数组,并将此数组放入 RecursiveArrayIterator 的一个实例中,并迭代所有内容,将其放入 RecursiveIteratorIterator。

    这样,整个数组,包括它的顶层,都会被迭代。

    因为你滥用 RecursiveArrayIterator 作为信息的载体,所以顶层对象没有被迭代。

    建议的简单示例有些讨厌,但演示了原理:

    $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";
    }
    

    结果输出:

    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
    

    它的输出并不完全相同,但我的观点是,您可以迭代结构,而无需让每个节点都成为 RecursiveArrayIterator 的实例。您可以添加任何内容,可以是数组,也可以是充当数组的对象,或者可以有效迭代的对象。

    【讨论】:

    • 说真的,var_dump($root) :)?
    • 这让事情变得更清楚了。谢谢你。不过,我真正想弄清楚的是使用某些 Spl 迭代器以类似方式嵌套对象的最佳方式。
    猜你喜欢
    • 2010-10-05
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多