大家一起來分析一下下面這段代碼:
<?php $arr = array(); $arr["abc"] = array("sex" => 100, "age" => 18); $arr["bcd"] = array("sex" => 200, "age" => 19); $arr["cde"] = array("sex" => 250, "age" => 17); $arr2 = array(); foreach ($arr as $name => $item) { $item2 = &$arr2[$name]; $item2["sex"] = $item["sex"] + 300; $item2["age"] = $item["age"] + 2; } //unset($item2); foreach ($arr2 as $name => $item2) { echo "name: $name, age: " . $item2['age'] . ", sex: " . $item2['sex'] . PHP_EOL; } echo "too little".PHP_EOL; //unset($item2); $item2 = array("age" => 30, "sex" => 1000); print_r($item2); echo "next step".PHP_EOL; foreach ($arr2 as $name => $item) { echo "name: $name, age: " . $item['age'] . ", sex: " . $item['sex'] . PHP_EOL; }
如果你覺得上面的代碼的執行結果是
name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 19, sex: 550 too little Array ( [age] => 30 [sex] => 1000 ) next step name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 19, sex: 550
或者是
name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 21, sex: 500 too little Array ( [age] => 30 [sex] => 1000 ) next step name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 21, sex: 500
那么你就應該繼續往下看了。因為上面兩個結果都是錯誤的,真正的執行結果如下:
name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 21, sex: 500 too little Array ( [age] => 30 [sex] => 1000 ) next step name: abc, age: 20, sex: 400 name: bcd, age: 21, sex: 500 name: cde, age: 30, sex: 1000
為什么會是這樣一個結果呢?
因為在第一個引用賦值的foreach循環結束以后,$item2依然引用着$arr2數組的最后一個元素。而第二個foreach循環的時候,相當於把$arr2數組的元素依次賦值給$item2,也就相當於賦值給最后一個元素。也就是說,在第二個foreach遍歷的過程中,$arr2數組的變化是這樣的:
循環到第1個元素時的數組:[1, 2, 1] 循環到第2個元素時的數組:[1, 2, 2] 循環到第3個元素時的數組:[1, 2, 2]
而后的
$item2 = array("age" => 30, "sex" => 1000);
是為了告訴大家引用關系依然存在,並且,直接賦值也會導致引用的數據發生變化。(其實,第二個foreach循環時也是使用的直接賦值,只是有點不好觀察出來)
那么,怎樣才能將$item2與$arr2的最后一個元素的引用關系去掉呢?其實很簡單,只要添加以下語句就可以了。也就是源代碼中注釋的地方。
unset($item2);
這也可以說是PHP的一個小坑,對於PHP新手來說,很容易犯這種錯誤而雲里霧里,不知所措。希望這篇文章能幫到這樣的新手。