0

RecursiveFilterIterator受け入れたくないオブジェクトを返さずに、受け入れたくないオブジェクトの子にアクセスするのに苦労しています。

と の 2 種類のNodeオブジェクトがNodeTypeAありNodeTypeA、どちらも抽象型を拡張しNodeます。

abstract class Node implements Countable, RecursiveIterator
{
    protected $children;

    public function __construct( array $children = array() )
    {
        $this->children = $children;
    }

    public function count()
    {
        return count( $this->children );
    }

    public function hasChildren()
    {
        if( !$this->valid() )
        {
            return false;
        }

        return count( $this->current() ) > 0;
    }

    public function getChildren()
    {
        return $this->current();
    }

    public function rewind()
    {
        reset( $this->children );
    }

    public function key()
    {
        return key( $this->children );
    }

    public function valid()
    {
        return null !== $this->key();
    }

    public function current()
    {
        return current( $this->children );
    }

    public function next()
    {
        next( $this->children );
    }
}

class NodeTypeA extends Node {}

class NodeTypeB extends Node {}

...私はこれを定義しましたRecursiveFilterIterator

class RecursiveNodeFilterIterator
    extends RecursiveFilterIterator
{
    public function __construct( RecursiveIterator $iterator, $kind )
    {
        parent::__construct( $iterator );

        $this->kind = $kind;
    }

    public function accept()
    {
        $current = $this->current();
        return $this->hasChildren() || $current instanceof $this->kind;
    }

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

次に、このスニペットを実行すると:

header( 'Content-Type: text/plain; charset=utf-8' );

$nodes = new NodeTypeA( array(
    new NodeTypeB( array(
        new NodeTypeA( array(
            new NodeTypeB( array(
                new NodeTypeA(),
                new NodeTypeA()
            ) ),
        ) ),
        new NodeTypeA( array(
            new NodeTypeB( array(
                new NodeTypeB( array(
                    new NodeTypeA(),
                    new NodeTypeB()
                ) ),
            ) )
        ) ),
        new NodeTypeB()
    ) ),
    new NodeTypeA()
) );

$rii = new RecursiveIteratorIterator(
    new RecursiveNodeFilterIterator( $nodes, 'NodeTypeA' ),
    RecursiveIteratorIterator::SELF_FIRST
);

foreach( $rii as $node )
{
   echo str_repeat( '  ', $rii->getDepth() ) . get_class( $node ) . PHP_EOL;
}

私はこの結果を得ることを望んでいました:

  NodeTypeA
      NodeTypeA
      NodeTypeA
  NodeTypeA
        NodeTypeA
NodeTypeA

...しかし得た:

NodeTypeB
  NodeTypeA
    NodeTypeB
      NodeTypeA
      NodeTypeA
  NodeTypeA
    NodeTypeB
      NodeTypeB
        NodeTypeA
NodeTypeA

つまり、反復NodeTypeB時に、子を持つオブジェクトも返します。フィルターが可能なすべての子ノードを訪問するために、RecursiveNodeFilterIterator::accept()を定義したので、これは理にかなっています。return $this->hasChildren() || ...

実際にノード自体を返さずにRecursiveNodeFilterIterator子ノードにアクセスする方法はありますか?NodeTypeBNodeTypeB

4

1 に答える 1

2

簡単なオプションは、関心のある項目RecursiveIteratorIteratorのみをフィルター反復子でラップすることです。accept

(コメントから回答に移動しました)

于 2013-12-16T09:41:08.783 に答える