php中使用& 导致的一个bug | 海诺博客

1,039 阅读1分钟

bug 来源

今日徒弟在对数据进行处理时 用了多个foreach,且在foreach的时候对value进行了引用,最后在循环处理时,发现之前的一个一维数组的最后一个元素变成了一个数组,这个bug可以精简为两个foreach。

bug 复现

具体代码如下:

$a=[
	1=>['a','b','c'],
	2=>['v','d','r'],
	3=>['v4','d4','r4'],
	4=>['v5','d5','r5']
];
$b=[1=>55,2=>5,3=>677,4=>9];
foreach($b as &$value){
   $value=intval($value);
	if($value<1){
	exit('数据有误!');
	}
}
foreach($a as $key=>$value){
	if($key==4){
		var_dump($b[$key]);
	}
}

这个时候你会发现输出是这样的

array(3) {
  [0]=>
  string(2) "v5"
  [1]=>
  string(2) "d5"
  [2]=>
  string(2) "r5"
}

变更下代码

$a=[
	1=>['a','b','c'],
	2=>['v','d','r'],
	3=>['v4','d4','r4'],
	4=>['v5','d5','r5']
];
$b=[1=>55,2=>5,3=>677,4=>9];
foreach($b as &$value){
   $value=intval($value);
	if($value<1){
	exit('数据有误!');
	}
}
   var_dump($b);
foreach($a as $key=>$value){
	if($key==4){
		var_dump($b[$key]);
	}
}

会看到这样

array(4) {
  [1]=>
  int(55)
  [2]=>
  int(5)
  [3]=>
  int(677)
  [4]=>
  &int(9)
}
array(3) {
  [0]=>
  string(2) "v5"
  [1]=>
  string(2) "d5"
  [2]=>
  string(2) "r5"
}

bug 产生原因

在【4】=>&int(9) 这个int什么鬼啊。这里其实就是引用的原因

产生条件一

必须是key有关联,例如第一数组的key是第二个数组的索引,或者第一个数组的元素的某个key的值是B的索引key

产生条件二

必须是在循环第一个数组之前循环第二个数组,且循环第二数组时使用的是引用传值

产生条件三

必须是两个foreach使用的相同的as后的参数,例如本例 形参均为$value

产生条件四

在第二个froeach循环中使用了$value

bug解析

原因就是 这个引用 ,第一个循环 将$value设置为引用后,第二个循环的$value 自动使用了第一个循环最后一个$value的内存,第二个value变化,也会引起第一个循环的最后一个$value变化。

解决办法

在每一个使用引用方式的foreach后增加一个unset($value);

最终无bug代码

$a=[
	1=>['a','b','c'],
	2=>['v','d','r'],
	3=>['v4','d4','r4'],
	4=>['v5','d5','r5']
];
$b=[1=>55,2=>5,3=>677,4=>9];
foreach($b as &$value){
   $value=intval($value);
	if($value<1){
	exit('数据有误!');
	}
}
//循环结束后,将循环的形参干掉
  unset($value);
foreach($a as $key=>$value){
	if($key==4){
		var_dump($b[$key]);
	}
}