很幸运,我又给自己创造了一个bug。
就是原本一直正常的功能,突然被用户4月6号发现了一个bug:
设备一直全部都是运行状态,有一台设备却调皮地“灰“头土脸了。

但奇妙的是,我压根儿就不知道自己是怎么创造出这个bug的。
费了一番功夫,最终找出问题出在下面这段代码上:

代码中的问题,我将在文末揭晓。如果你有兴趣找bug的话,可以先瞅瞅。
本文是翟码农个人博客PHP分类下的原创文章,转载请注明出处:http://www.zhai14.com/blog/why-I-made-a-bug-again-1.html,我怎么又给自己创造了一个bug系列(一)
不过本文的重点,我不是要跟大家分享我怎么找到bug的,而是和大家分享:
我是怎么不知不觉给自己创造了bug?
经过日志追溯,发现2023年3月3号本人改动了上面那段代码。改动之前的代码如下所示:
//批量获取设备当前数据
public function getMultiDeviceCurrentInfo($arrDeviceId){
$model = new EquipmentMongo();
return $model->getCurrentInfoByDeviceIds($arrDeviceId);
}
//批量获取设备当前状态
public function getMultiDeviceCurrentStatus($arrDeviceId)
{
$deviceInfo = $this->getMultiDeviceCurrentInfo($arrDeviceId);
$newList = [];
foreach($deviceInfo as $item){
if(isset($item['status']) && false === strpos($item['device_id'], 'GTRY_')){
//电表采集status暂时有误,用connection_status
$status = $item['status'];
}else{
$status = $item['connection_status'];
}
$statusInfo = $this->getRunStatus($status); //电这块没有status属性数据
$newList[] = array(
'device_id' => $item['device_id'],
'status_run_text' => $statusInfo['status_run_text'],
'status_run' => $statusInfo['status_run']
);
}
//模拟数据
foreach($arrDeviceId as $deviceId){
if( in_array($deviceId, array('SH-PD-01', 'SH-PD2-01', '729-11SY', 'SH-PD-099'))){
$item = [];
$item['device_id'] = $deviceId;
$item['status_run_text'] = 'run';
$item['status_run'] = 1;
$newList[] = $item;
}
}
return array_column($newList, 'status_run_text', 'device_id');
}
改动之后如下所示:
//批量获取设备当前数据
public function getMultiDeviceCurrentInfo($arrDeviceId){
$model = new EquipmentMongo();
$list = $model->getCurrentInfoByDeviceIds($arrDeviceId);
$currentTime = strtotime(DateUtil::getCurrentDatetime());
foreach($list as &$item){
if(isset($item['status']) && false === strpos($item['device_id'], 'GTRY_')){
if($currentTime - strtotime($item['time']) > 300){
//超过5分钟没更新数据,暂认为数据采集中断
$status = "interrupt";
}else{
$status = $item['status'];
}
}else{
//电表采集status暂时有误,用connection_status
$status = $item['connection_status'];
}
$statusInfo = $this->getRunStatus($status);
$item['status_run_text'] = $statusInfo['status_run_text'];
$item['status_run'] = $statusInfo['status_run'];
}
//模拟数据
foreach($arrDeviceId as $deviceId){
if( in_array($deviceId, array('SH-PD-01', 'SH-PD2-01', '729-11SY', 'SH-PD-099'))){
$item = [];
$item['device_id'] = $deviceId;
$item['status_run_text'] = 'run';
$item['status_run'] = 1;
$list[] = $item;
}
}
return $list;
}
//批量获取设备当前状态
public function getMultiDeviceCurrentStatus($arrDeviceId)
{
$deviceInfo = $this->getMultiDeviceCurrentInfo($arrDeviceId);
return array_column($deviceInfo, 'status_run_text', 'device_id');
}
可以看出,正是我将设备状态status_run这个数据,转移到getMultiDeviceCurrentInfo这个方法里,然后一不小心,就不知不觉给自己埋藏了bug。
我的bug就是:
第二个foreach中重置$item变量,会将第一个foreach中最后一个$item元素给重置为空,因为恰巧$item用了引用,所以最终$list里就少了一台设备数据
这也就是为何用户从界面上发现有台设备状态为离线(程序给了默认值,如果不是运行状态,就默认为离线)。
本人貌似犯了好几次这种白白耽误自己功夫的错误,今天特记之,希望日后能多加注意:
写多个foreach循环遍历时,尽量用不同命名的$item变量
除非你特意需要这么做,例如:我要给自己的明天任务留一个bug。