【问题标题】:ArrayObject::offsetUnset advances the internal pointer in an unexpected wayArrayObject::offsetUnset 以意想不到的方式推进内部指针
【发布时间】:2018-04-24 11:31:01
【问题描述】:

大家好,我有以下场景

$col = new ArrayObject();

for ($i = 0; $i < 5; $i++)
{
    $objItem = new stdClass;
    $objItem->someVar = $i;
    $col->append($objItem);
}

现在我想通过offsetUnset 删除一些密钥并执行以下操作

foreach($col AS $key => $objItem)
{
    if ($key == 2)
    {
        $col->offsetUnset($key);
    }
    echo $key.'\n';
}

现在有趣的是意外的输出

0
1
2
4

为了更好的说明 - 如果你把一个继续像

foreach($col AS $key => $objItem)
{
    if ($key == 2)
    {
        $col->offsetUnset($key);
        continue;
    }
    echo $key.'\n';
}

输出是

0
1
4

我从没想过它会绕过 key 数字 3 在这个 3 只是因为我删除了前一个项目 - 看起来内部指针增加了两次或类似的东西......

请记住,我也尝试过类似的方法

$it = $col->getIterator();

foreach($it AS $key => $objItem)
{
    if ($key == 2)
    {
        $col->offsetUnset($key);
    }
    echo $key."\n";
}

输出是一样的

问题:

这是正常行为还是我在这里忽略了一些重要的事情?

pS:正如 nigel Ren 指出的那样,这可能与 Php, Spl, ArrayIterator 重复,我必须指出我在这里寻找 ArrayObject 解决方案,但没有找到任何解决方案(我现在知道 ArrayIterator 问题可能是相同)-但我永远不会猜到这些是相互关联的-在这方面,我恳求不要结束这个问题,因为它也可能对其他人有所帮助

【问题讨论】:

  • 请分享任何现场演示?
  • 检查 var_dump($col); 你会发现这不是问题,它按预期工作(索引从 0 开始,所以 key ==2 代表数组的第三个值)
  • @AlivetoDie 我的数组对象包含 5 个值 - 键值 2 是第三个元素,但在删除键值 2 后我没有得到键值为 3 的第四个元素 ...
  • Php, Spl, ArrayIterator的可能重复
  • @NigelRen 我会检查它 - 但请记住,我在这里寻找 ArrayObject 解决方案但没有找到任何(我现在知道 ArrayIterator 问题可能相同) - 但是我永远不会猜到这些是相互关联的——在这方面,我恳求不要结束这个问题,因为它也可能对其他人有所帮助

标签: php


【解决方案1】:

这个Bug的解决方法其实很简单,贴在here 由名为 Tsounabe 的用户提供。

我把他的解决方案放在这里 - 只有一个变化 - 他指的是 ArrayIterator 而我说的是 ArrayObject - 但两者都使用相同的功能 getArrayCopy

foreach($col->getArrayCopy() AS $key => $objItem)
{
    if ($key == 2)
    {
        $col->offsetUnset($key);
        continue;
    }
    echo $key.'\n';
}

结论

为了避免这个错误,这里唯一令人满意的解决方案是使用getArrayCopy(),它记录在官方 PHP 站点的https://secure.php.net/manual/de/arrayobject.getarraycopy.php

【讨论】:

    【解决方案2】:

    在您的代码中,它在$col-&gt;offsetUnset($key); 之后重置对象key,并在重置后继续下一个键3,它将-&gt;someVar 值为4 的元素,这就是您获得此输出的原因。

    因此您可以简单地使用另一个迭代来打印您的对象。它会工作的。

    Live demo

    输出

    0
    1
    3
    4
    

    【讨论】:

    • 你能像我一样分享一个现场演示吗?
    • 如果您在 offsetUnset 之后放置 continue - 您会看到它跳过 2 个键
    • 使用另一个迭代打印,似乎offsetUnset正在重置keys并继续下一个索引。
    • 是的,事实上这就是我所做的——但老实说,它并没有解决问题,因为我没想到会出现这种行为,而且我认为我不应该这样做——它在一个非常复杂的场景中花了大约 90 分钟才发现这不是我的错误......
    猜你喜欢
    • 1970-01-01
    • 2015-05-31
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多