简体   繁体   English

RecursiveFilterIterator:如何不接受对象,但仍然访问他们的孩子?

[英]RecursiveFilterIterator: how to not accept objects, but still visit their children?

I'm having difficulty to get RecursiveFilterIterator to visit children of objects that I don't want to accept, without also returning the unacceptable object. 我很难让RecursiveFilterIterator访问我不想接受的对象的子对象,而不返回不可接受的对象。

I have two types of Node objects: NodeTypeA and NodeTypeA , that both extend abstract type Node : 我有两种类型的Node对象: NodeTypeANodeTypeA ,它们都扩展了抽象类型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 {}

... for which I defined this RecursiveFilterIterator : ...我为此定义了这个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 );
    }
}

Then, when I run this snippet: 然后,当我运行此代码段时:

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

I was hoping to get this result: 我希望得到这个结果:

  NodeTypeA
      NodeTypeA
      NodeTypeA
  NodeTypeA
        NodeTypeA
NodeTypeA

... but got: ......但得到了:

NodeTypeB
  NodeTypeA
    NodeTypeB
      NodeTypeA
      NodeTypeA
  NodeTypeA
    NodeTypeB
      NodeTypeB
        NodeTypeA
NodeTypeA

In other words, on iterating, it also returns NodeTypeB objects when they have children. 换句话说,在迭代时,它还会在有子NodeTypeB时返回NodeTypeB对象。 This makes sense, since in RecursiveNodeFilterIterator::accept() I have defined return $this->hasChildren() || ... 这是有道理的,因为在RecursiveNodeFilterIterator::accept()我定义了return $this->hasChildren() || ... return $this->hasChildren() || ... , in order for the filter to visit all possible child nodes. return $this->hasChildren() || ... ,以便过滤器访问所有可能的子节点。

Is there a way to have RecursiveNodeFilterIterator visit child nodes of NodeTypeB without actually returning the NodeTypeB nodes themselves? 有没有办法让RecursiveNodeFilterIterator访问NodeTypeB子节点而不实际返回NodeTypeB节点本身?

A simple option is to wrap the RecursiveIteratorIterator with a filter iterator that only accept s the items that you are interested in. 一个简单的选择是使用过滤器迭代器包装RecursiveIteratorIterator ,该迭代器仅accept您感兴趣的项目。

(Moved from comment to answer) (从评论转到回答)

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

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