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
子ノードにアクセスする方法はありますか?NodeTypeB
NodeTypeB