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]);
}
}