使用 foreach ($arr as &$value) 修改陣列元素後,$value 仍保留對最後一個元素的引用。後續若重複使用同變數名 $value(如另一個 foreach),會意外修改原陣列最後一個元素。
$arr = ['a', 'b', 'c'];
$arr2 = ['d', 'e', 'f'];
foreach ($arr as &$value) {
$value .= '4'; // 修改 $arr 元素
}
// 此時 $value 參考 $arr[2] ('c4')
foreach ($arr2 as $value) { // 未加 &,但 $value 仍是引用!
// $arr[2] 會跟著變成 'd', 'e', 'f'
}
foreach ($arr as $value) {
echo $value . "\n"; // 輸出 a4, b4, b4 (預期 a4, b4, c4)
}
PHP foreach 的引用變數在迴圈結束後不會自動銷毀,繼續指向最後一個元素。後續同名變數若不加 &,仍會複用該引用(PHP 內部優化機制)。
foreach ($arr as &$value) {
$value .= '4';
}
unset($value); // 關鍵:斷開引用關聯
foreach ($arr2 as $value) { // 現在安全了
// ...
}
unset($value):每次 foreach (... as &$v) 結束後立即解除引用。$val、$item、$element 避免重名碰撞。foreach ($arr as $key => $value) 修改:$arr[$key] = ... 避免引用風險。// 推薦寫法 1:明確 unset
foreach ($items as &$item) {
$item['processed'] = true;
}
unset($item);
// 推薦寫法 2:不使用引用,透過鍵值修改
foreach ($items as $key => $item) {
$items[$key]['processed'] = true;
}
// 推薦寫法 3:陣列函數式處理(PHP 5.3+)
$items = array_map(function($item) {
$item['processed'] = true;
return $item;
}, $items);
「在 foreach 迴圈中,若使用引用,迴圈結束後 $value 仍保留對最後一個元素的引用。建議使用 unset() 將其銷毀。」(PHP Manual - foreach)