SplObjectStorage - 分离行为

时间:2015-12-17 15:21:15

标签: php spl

我发现this comment on the PHP doc page并对此感到惊讶。

他的评论可能不是最好的,但我想知道为什么以下脚本的输出是"留在存储中:2"?为什么"输出:"没有显示" 2"。

我希望在分离所有对象后存储空为空。

<?php
class A {
    public $i;
    public function __construct($i) {
        $this->i = $i;
    }
}

$container = new \SplObjectStorage();

$container->attach(new A(1));
$container->attach(new A(2));
$container->attach(new A(3));
$container->attach(new A(4));
$container->attach(new A(5));

foreach ($container as $item) {
    echo $item->i . "\n";
    $container->detach($item);
}
echo "== Left in storage ==\n";
foreach ($container as $item) {
    echo $item->i . "\n";
}

/* Outputs:
1
3
4
5
== Left in storage ==
2
*/

1 个答案:

答案 0 :(得分:4)

这是因为通过detach foreach循环内的对象,这可以防止SplObjectStorage::next正常工作。我能够在PHP文档的this用户贡献说明中找到这些信息(所以请考虑它的价值)。

  

如果要在迭代期间分离对象,则应在调用next()之前取消引用对象,并在next()之后分离引用

还有一个bug报告可用,显然它不起作用的原因是,在分离时,方法倒带容器&# 39; s内部数组指针,这是在循环内部分离时造成破坏的原因。

在您的情况下,按照该注释,您可以像这样更改从存储容器中删除对象的循环,它应该按预期工作:

$container->attach(new A(1));
$container->attach(new A(2));
$container->attach(new A(3));
$container->attach(new A(4));
$container->attach(new A(5));

$container->rewind();
while ($container->valid()) {
    $item = $container->current();
    echo $item->i . "\n";
    $container->next();
    $container->detach($item);
}
/* Outputs:
1
2
3
4
5
== Left in storage ==
*/