PHP递归迭代器离开

时间:2013-06-18 00:45:49

标签: php iterator spl

我正在努力更好地理解PHP中的迭代器。对于此测试,我想制作一个项目树,并使用不同的RecursiveIteratorIterator模式列出它们。 :: SELF_FIRST和:: CHILD_FIRST模式正如我所期望的那样工作。但是,当我想列出叶子时,它不会。在实现中必须有一些东西,它不允许该模式正常工作,因为它什么都没打印出来。我的Obj::hasChildren()方法有问题吗?

这是测试类:

class Obj implements \RecursiveIterator {
    public $children = array();

    private $position;

    private $name;

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

    public function valid()
    {
        return isset($this->children[$this->position]);
    }

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

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

    public function rewind()
    {
        $this->position = 0;
    }

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

    public function hasChildren()
    {
        return !empty($this->children[$this->position]);
    }

    public function getChildren()
    {
        return $this->children[$this->position];
    }

    public function __toString()
    {
        return $this->name;
    }
}

这是测试:

use RecursiveIteratorIterator as RII;

$o1 = new Obj('Root');

$i1 = new Obj('Item 1');
$i12 = new Obj('Subitem 2');
$i1->children[] = new Obj('Subitem 1');
$i1->children[] = $i12;

$i12->children[] = new Obj('Subsubitem 1');
$i12->children[] = new Obj('Enough....');

$o1->children[] = $i1;
$o1->children[] = new Obj('Item 2');
$o1->children[] = new Obj('Item 3');

foreach (new RII($o1, RII::LEAVES_ONLY) as $o) {
    echo "<br>" . $o;
}

1 个答案:

答案 0 :(得分:2)

您所假设的是指向正确的方向,您的hasChildren()方法存在问题。将其与valid()current()方法进行比较,您可能已经看到总是返回true。

因为只要有current()hasChildren()就会返回true:

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

public function hasChildren()
{
    return !empty($this->children[$this->position]);
}

相反,您想要测试当前元素是否包含子元素:

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

给你输出的细微差别:

Subitem 1
Subsubitem 1
Enough....
Item 2
Item 3

始终为TRUE返回hasChildren()RecursiveIteratorIterator无法检测到任何离开。根据树的概念,这是不可能的,但在遍历过程中 - 正如你用“bug”所证明的那样 - 显然可能:)

另见(如果可以的话):