通过引用浏览数组正在改变它(没有完成任何操作)

时间:2014-12-15 09:44:53

标签: php arrays

编辑:不要阅读相关主题,下面的答案是明确的并给出了解决方案,而另一个主题只是说明了问题。

我在这里有些奇怪的事情

我的代码如下所示:

        var_dump($resultFlatTree);
        foreach($resultFlatTree as &$element)
        {
            /*if(isset($element["action"]) && $element["action"] == "new")
            {
                //let's save the original ID so we can find the children
                $originalID = $element["id"];
                //now we get the object
                $newObject = $setUpForDimension->createAnObject($dimension,$element,$customer);
                $element['id'] = $newObject->getId();
                echo "new";
                //and let's not forget to change the parent_id of its children
                $arrayFunctions->arrayChangingValues($resultFlatTree,"parent_id",$element['id'],$originalID);
                $em->persist($newObject);                                                             
            } */               
        }            
        $em->flush();
        var_dump($resultFlatTree);

foreach中的代码被注释,以确保它不是我正在做的更改数组。

这里是foreach之前的数组:

array(3) {
  [0]=>
  array(10) {
    ["id"]=>
    int(2)
    ["name"]=>
    string(7) "Revenue"
    ["code"]=>
    string(6) "700000"
    ["sense"]=>
    string(2) "CR"
    ["lft"]=>
    int(1)
    ["lvl"]=>
    int(2)
    ["rgt"]=>
    int(1)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00D"
    ["parent_id"]=>
    int(1)
  }
  [1]=>
  array(10) {
    ["id"]=>
    int(3)
    ["name"]=>
    string(7) "Charges"
    ["code"]=>
    string(6) "600000"
    ["sense"]=>
    string(2) "DR"
    ["lft"]=>
    int(3)
    ["lvl"]=>
    int(2)
    ["rgt"]=>
    int(4)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00P"
    ["parent_id"]=>
    int(4)
  }
  [2]=>
  array(10) {
    ["id"]=>
    int(4)
    ["name"]=>
    string(6) "Energy"
    ["code"]=>
    string(6) "606000"
    ["sense"]=>
    string(2) "DR"
    ["lft"]=>
    int(2)
    ["lvl"]=>
    int(1)
    ["rgt"]=>
    int(5)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00E"
    ["parent_id"]=>
    int(1)
  }
}

然后:

array(3) {
  [0]=>
  array(10) {
    ["id"]=>
    int(2)
    ["name"]=>
    string(7) "Revenue"
    ["code"]=>
    string(6) "700000"
    ["sense"]=>
    string(2) "CR"
    ["lft"]=>
    int(1)
    ["lvl"]=>
    int(2)
    ["rgt"]=>
    int(1)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00D"
    ["parent_id"]=>
    int(1)
  }
  [1]=>
  array(10) {
    ["id"]=>
    int(3)
    ["name"]=>
    string(7) "Charges"
    ["code"]=>
    string(6) "600000"
    ["sense"]=>
    string(2) "DR"
    ["lft"]=>
    int(3)
    ["lvl"]=>
    int(2)
    ["rgt"]=>
    int(4)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00P"
    ["parent_id"]=>
    int(4)
  }
  [2]=>
  &array(10) {
    ["id"]=>
    int(4)
    ["name"]=>
    string(6) "Energy"
    ["code"]=>
    string(6) "606000"
    ["sense"]=>
    string(2) "DR"
    ["lft"]=>
    int(2)
    ["lvl"]=>
    int(1)
    ["rgt"]=>
    int(5)
    ["root"]=>
    int(1)
    ["$$hashKey"]=>
    string(3) "00E"
    ["parent_id"]=>
    int(1)
  }
}

如您所见,最后一个元素现在已经更改并且是引用的。 这完全扰乱了我之后使用数组进行的处理。

这是正常行为吗? 我怎么能避免它?

1 个答案:

答案 0 :(得分:3)

当您通过引用传递foreach语句时,您真的应该阅读文档:)

http://php.net/manual/en/control-structures.foreach.php

  

为了能够直接修改循环中的数组元素,在$ value之前加上&amp ;.在这种情况下,该值将通过引用分配。

<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element
?>

即使在foreach循环之后,$ value和最后一个数组元素的引用仍然存在。建议通过unset()销毁它。

基本上,它说当你通过ref时,由于内部指针,它将保持锁定在最后一项上。

第二位用户评论40分:

“$ value的引用和最后一个数组元素在foreach循环之后仍然存在。建议通过unset()销毁它。”

我不能强调文档的这一点!这是一个简单的例子,说明为什么必须这样做:

<?php
$arr1 = array("a" => 1, "b" => 2, "c" => 3);
$arr2 = array("x" => 4, "y" => 5, "z" => 6);

foreach ($arr1 as $key => &$val) {}
foreach ($arr2 as $key => $val) {}

var_dump($arr1);
var_dump($arr2);
?>

输出结果为:

array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(6) }
array(3) { ["x"]=> int(4) ["y"]=> int(5) ["z"]=> int(6) }

注意$ arr1中的最后一个索引现在是$ arr2中最后一个索引的值!

如果您在该链接中查找“参考”,您会发现更多有趣的评论。

TL; DR: 它有点搞笑/错误/怪异/未打补丁。 了解编写代码并为其创建空间时的含义。