记两次循环语句中数组、变量未声明(未销毁)导致的bug

版权声明:本文为本小白原创文章,(转载请说明出处,标明链接) 文中若有错误,敬请指正!——————编程不过是一门失传的艺术的别名,这门艺术的名字叫做“思考”。 https://blog.csdn.net/qq_32737755/article/details/84978762

上个月稀里糊涂的犯了两次差不多的问题.....特记下,以示警醒。

第一次:悲催的改了三次代码...

根据特定条件,打印curl语句,然后放到 .sh文件中,用Shell来执行。

查询表***,根据产品id和结束时间(大于当前时间)查询用户。通过接口执行特定语句(就是我打印出来的语句)。

第一次代码:

$config = array(
	array(1,2,3,4),
	array(5,6,7,8)
	);
foreach ($config as $item) {
	$sql = "select * from (select userid,enddate from tablename where id in (?,?,?) and enddate > now() order by enddate desc) as a group by userid";
	$sth = DB_Pdo::instance()->get_dbh()->prepare($sql);
	$sth->execute(array($item[0],$item[1],$item[1]));
	$arr = $sth->fetchAll(PDO::FETCH_ASSOC))
	$sth = null;
	foreach ($arr as  $value) {
		echo "curl '链接(此处省略)&sid=".$item[3]."&enddate=".$value['enddate']."&userid=".$value['userid']."'\n";
	}
}

这个代码在代码层面是没问题的,但是当数据量比较大的时候就会出现问题了,嵌套的sql语句执行起来很耗费时间、资源,可能会导致宕机。因此废弃,换一种方式。 ......... 悲剧即将到来。

第二次代码:

$config = array(
	array(1,2,3,4),
	array(5,6,7,8)
	);
$userid_arr = array();
foreach ($config as $item) {
	$sql = "select userid,enddate from tablename where id in (?,?,?) and enddate > now() order by id";
	$sth = DB_Pdo::instance()->get_dbh()->prepare($sql);
	$sth->execute(array($item[0],$item[1],$item[1]));
	while (false !== $row = $sth->fetch(PDO::FETCH_ASSOC)) {
		if($userid_arr[$row['userid']] < $row['enddate']){
			$userid_arr[$row['userid']] = $row['enddate'];
		}
	}
	$sth = null;
	foreach ($userid_arr as $key => $value) {
		echo "curl '链接(此处省略)&sid=".$item[3]."&enddate=".$value."&userid=".$key."'\n";
	}
}

上边代码,改了sql语句,但是用到了循环。。。大眼一看,好像没问题,但是当运行的时候就会发现,curl语句比第一次代码执行出来的要多一部分。然后才发现循环语句中的 $userid_arr 是在foreach外面声明的,也就是说foreach循环第二次的时候$userid_arr数组内依然包含第一次循环后的结果,此时并不是空数组......然后第二次foreach的时候会把第一次循环过的数据再次循环。。。

所以又改了第三次,将$userid_arr = array(); 移到while上面,这样每次foreach的时候都会执行 userid_arr = array()

做循环的时候,遇到数组要么在之前声明,要么就在底部销毁。。。切记切记。。。然鹅。峩还是莫记得......不过这次是变量,不是数组了.........

第二次犯的错误和第一次类似

脚本代码大体上就是这样(代码过长,就缩略一下)

while(1){
    $result = 从队列取出来的数据;
    if(! $result){
        echo "*";
        sleep(1);
    }elseif($result){

        处理 $result 数据;
        *
        *
        *
        *
        *一大堆代码(省略)···

        if(isset($result['appflag']) && isset($result['appid'])){
            $appflag = $result['appflag'];
            $appid = $result['appid'];
        }
        
        *
        *
        *
        *
        *又一大堆代码(省略)···
        
        if($appflag && $appid){
             危险代码........
        }
    }
}

$result 是从kafka取出来的数组,但是数据还不一样,有些包含了 $result['appflag'] 和 $result['appid']。。 有些数组则没有这两项。这就是噩梦的开端,执行了之后,发现。。。唉~~~ 没有包含$result['appflag'] 和 $result['appid']的数据,也执行了“危险代码”。仔细检查发现:if($appflag && $appid) 并未生效,看了下发现是while循环,当运行了一次包含了 $result['appflag'] 和 $result['appid']的数据后,$appflag 、 $appid 这两个变量就一直存在了.....再循环的时候 $appflag && $appid 就一直为true了,代码也就一直执行了。

代码长并不是未声明$appflag 和 $appid 的借口,幸好及时发现,在执行完“危险代码”后,增加销毁$appflag 、 $appid 两个变量的代码,直接unset掉。。。或者代码中一直使用$result['appflag'],$result['appid'] 不做赋值操作,也不会出现这种问题。

总之总之,循环操作一定要倍加小心,用到数组要声明,用到循环内用到判断一定要仔细看下条件是否需要做处理。。。

切记,以上。

猜你喜欢

转载自blog.csdn.net/qq_32737755/article/details/84978762