«
PHP里for循环引用变量未unset所带来的问题

时间:2026-4-24    作者:范文泉    分类: php


<?php
$items = [['a' => '1', 'b' => 1], ['a' => '2', 'b' => 2], ['a' => '3', 'b' => 3]];
foreach ($items as &$item) {
    // 什么都没做
}
// 此时 $item 是 $items[2] 的引用

$items[] = ['a' => '4', 'b' => 4];
// 现在 $items 有4个元素:索引0,1,2,3
// $item 仍然引用 $items[2](原来的第3个元素)

for ($i = 0; $i < count($items); $i++) {
    $item = $items[$i];
    // 第1次循环:$i=0,$item = $items[0]
    //    因为 $item 是引用,所以 $items[2] 被修改为 $items[0]
    // 第2次循环:$i=1,$item = $items[1]  
    //    $items[2] 被修改为 $items[1]
    // 第3次循环:$i=2,$item = $items[2]
    //    $items[2] 被修改为 $items[2](自身,不变)
    // 第4次循环:$i=3,$item = $items[3]
    //    $items[2] 被修改为 $items[3]
}

var_dump($items);

实际输出结果

array(4) {
  [0]=> array(2) { ["a"]=> string(1) "1" ["b"]=> int(1) }
  [1]=> array(2) { ["a"]=> string(1) "2" ["b"]=> int(2) }
  [2]=> array(2) { ["a"]=> string(1) "4" ["b"]=> int(4) }  // 被改成了最后一个元素
  [3]=> array(2) { ["a"]=> string(1) "4" ["b"]=> int(4) }
}

详细执行过程

循环次数 执行语句 $items[2] 变成
初始状态 $item 引用 $items[2] ['a'=>'3','b'=>3]
i=0 $item = $items[0] ['a'=>'1','b'=>1]
i=1 $item = $items[1] ['a'=>'2','b'=>2]
i=2 $item = $items[2] ['a'=>'2','b'=>2] (不变)
i=3 $item = $items[3] ['a'=>'4','b'=>4]

最终结果

array(4) {
  [0]=> array(2) { ["a"]=> "1", ["b"]=> 1 }
  [1]=> array(2) { ["a"]=> "2", ["b"]=> 2 }
  [2]=> array(2) { ["a"]=> "4", ["b"]=> 4 }  // 重复了最后一项
  [3]=> array(2) { ["a"]=> "4", ["b"]=> 4 }
}

解决方法

foreach 后立即 unset($item),或者不使用引用。