文章大纲

php奇怪问题:数组在for循环中莫名其妙地发生了变化

2019-11-16 07:24:10

昨天写了一个很简单的接口,结果却因为遇上这么一个问题,调试了好久,简直要被自己整郁闷了。

郁闷就郁闷在一步步注释掉了代码,到最后简单到foreach里面只打印foreach外面的数组,结果却告诉我,foreach内外同一变量的值居然不一样,感觉脑子不够用了,实在想不通居然还会这样。

问题复现:

为了吸取经验,今天起早另写了一套简单的来复现了一下。

<?php

$stu_info = array(
	array('stu_no'=>'20190810111', 'name'=>'zhaicoder' ),
	array('stu_no'=>'20190810112', 'name'=>'laowang' ),
	array('stu_no'=>'20190810113', 'name'=>'zhangsan' ),
	array('stu_no'=>'20190810114', 'name'=>'xiaohei' ),
);

$stu_info_no_key = array_column($stu_info, null, 'stu_no');
foreach($stu_info_no_key as &$item){
	$item['score'] = 0;  //总分数
	$item['sort'] = 0;  //分数排名
}

$stu_score = array(
	array('stu_no'=>'20190810111', 'score'=>89),
	array('stu_no'=>'20190810111', 'score'=>96),
	// array('stu_no'=>'20190810111', 'score'=>82),
	// array('stu_no'=>'20190810112', 'score'=>80),
	// array('stu_no'=>'20190810112', 'score'=>77),
	// array('stu_no'=>'20190810112', 'score'=>90),
	// array('stu_no'=>'20190810113', 'score'=>99),
	// array('stu_no'=>'20190810114', 'score'=>90),
	// array('stu_no'=>'20190810114', 'score'=>97),
	// array('stu_no'=>'20190810114', 'score'=>94),
);
var_dump($stu_info_no_key);
foreach($stu_score as $item){
	var_dump($stu_info_no_key);
}

问题就是上面代码结尾处foreach内外的同样一个数组,打印出来的内容却不一样。


$stu_info_no_key的前三条数据都正常,就是最后一条不正常:数据像被狗啃了一样,name和sort不见了。

array(4) {
  ["20190810111"]=>
  array(4) {
    ["stu_no"]=>
    string(11) "20190810111"
    ["name"]=>
    string(9) "zhaicoder"
    ["score"]=>
    int(0)
    ["sort"]=>
    int(0)
  }
  ["20190810112"]=>
  array(4) {
    ["stu_no"]=>
    string(11) "20190810112"
    ["name"]=>
    string(7) "laowang"
    ["score"]=>
    int(0)
    ["sort"]=>
    int(0)
  }
  ["20190810113"]=>
  array(4) {
    ["stu_no"]=>
    string(11) "20190810113"
    ["name"]=>
    string(8) "zhangsan"
    ["score"]=>
    int(0)
    ["sort"]=>
    int(0)
  }
  ["20190810114"]=>
  &array(2) {
    ["stu_no"]=>
    string(11) "20190810111"
    ["score"]=>
    int(89)
  }
}


但是如果我把我中间的初始化工作换一种方式书写(如下所示),结果又是正常的。

foreach($stu_info as &$item){
	$item['score'] = 0;  //总分数
	$item['sort'] = 0;  //分数排名
}
$stu_info_no_key = array_column($stu_info, null, 'stu_no');

如果你有兴趣找问题原因,那你就止步于此,去试一试吧。


问题原因:

原因出在我写的两个foreach里面都是用的$item变量来遍历的,至于$stu_info_no_key数组的最后一条数据为何被啃了,其实不是被啃了,只是被$stu_score的数据给替换了,正好$stu_score数组的数据key值在$stu_info_no_key的数据里都有,才会造成这样一种错觉。


额,至于为何$stu_info_no_key最后一条数据被替换掉了,隐隐约约感觉跟我用的引用有关,但我仍没想明白程序是怎么一步一步的给我挖了这么个隐藏的大坑。


2019年11月16日 晚更新:

由于第一个foreach遍历完,$item引用就指向了$stu_info_no_key的最后一条数据。

在第二个foreach遍历时,就相当于把$stu_score的每条数据依次赋值给$item,这样就相当于直接修改了$item之前的内容值,也就是$stu_info_no_key的最后一条数据的值了。



收获的经验:

遍历foreach的内部变量尽量不用相同的变量名称





我要评论
评论列表