昨天在编写一个公众号的消息处理代码的时候,碰到了一个百思不得其解的问题,通过学哥不懈的努力,终于找到问题的原因,在感慨之余,觉得这是一个不错的编程调试经验,因此在这里分享给大家。
问题来由
学哥之前给一位朋友做了一个公众号,将公众号的消息回复设置为了编程模式,就是用户在公众号里面输入一些关键字,或者扫码事件,会触发这个程序去回复一些特殊的相应的消息给用户。
昨天朋友希望修改一下他的公众号代码,增加一个功能,就是在用户关注公众号的时候,发送一段欢迎的文本消息给用户。
因此学哥就开始修改之前的代码了。结果呢,按照预想的编写完之后,怎么测试都得不到预期的结果,把学哥折腾了好长时间,后来终于发现是一个非常非常低级的错误。学哥觉得这个错误,包括解决的过程还是很有代表性的,因此分享出来。
高手能一眼找到问题吗
学哥先贴出代码,然后说明预期的结果是什么,看看有没有哪位同道中人是大神,可以很快找出问题之所在。
代码很简单,是这样的:
学哥新增了一个函数getfirst,在里面写了发送欢迎文本消息给用户的处理代码。预期是当用户关注公众号的时候,这段程序执行,当$event变量等于'subscribe'的时候,也就是程序收到用户关注的消息事件的时候,执行echo getfrist这一行代码,就能让用户收到欢迎消息了。
学哥将公众号取消关注,然后重新关注,但是什么事情也没有发生,也就是说预期当中应该执行的getfirst这一行代码没有执行。
问题在哪里呢?
确认判断逻辑没有问题
学哥的第一个念头,是if判断逻辑出错了,那么有两种情况,第一种$event获得的值可能规定不是subscribe,有可能公众号的接口规范有变化,或者是自己记错了,关注事件产生的时候,event值不是subscribe。
于是学哥赶紧到公众号的开发文档里面去调查了一下,结果确认subscribe没错。那么if判断逻辑就是没问题。
那么只有一种可能,就是$event变量的值不是subscribe,那么它的值是什么呢?
增加log输出进行调试
学哥再次检查了代码,觉得没有问题,但是结果又不正确,这是只能启用log输出进行调试的屠龙术了。
修改代码如下:
学哥新增了3行代码,就是在当前目录下创建一个weixinlog.txt文件,将变量event的值写到log文件中。
这样,学哥看到这个值就能有更多信息可供判断。
再次取消关注,重新关注,结果当前目录下没有产生weixinlog.txt文件,纳尼,出什么问题了。
这3行代码不可能出错啊,都写过好多遍的代码了。
根据测试的结果来看,这3行代码必然运行了,因为运行效果可以判断第22行代码已经执行过,那么第19行代码必然会执行。
运行的文件一定是修改的文件吗
学哥再次认真的检查了代码,确定一件事:这段代码应该执行但却没有执行,可能运行的是一个“假代码”。
哈哈,意思就是运行的代码并不是修改的代码。
学哥只能再次从源头上开始检查,经过一番调查后,确认从源头上到这里整条路径没有错误,而且文件名,目录名全都确认过了,没有错误。
学哥再次懵逼了。
等等,还有一个源头,难道是域名?
想起前段时间为了完成域名备案,让搞硬件的朋友修改过域名解析,难道因为某些情况,域名解析没有按照要求改回来,还是解析到另外一台备份的机器上了?
赶紧来确认一下吧。
学哥立即编写了一个测试用的test.html文件:
然后将这个文件上传到了www目录下面,通过浏览器访问该域名下的这个网页文件,结果证实了,网页显示找不到这个文件。
说明域名指向的不是这个服务器了。真的是一波三折啊。
学哥赶紧通知搞硬件的朋友,把域名解析修改回来。
然后,再次刷新浏览器,终于看到这个测试网页了。
问题仍然存在
学哥松了一口气,心想问题应该解决了。
取消关注,重新关注,还是一样,没有显示欢迎消息。不会吧,学哥太悲催了。
去看看服务器当前目录下,果然生成了一个weixinlog.txt文件,打开一看,结果如下:
event:subscribe:
完全正确啊,怎么就不执行getfirst这一行呢。
看来没办法了,只能加强log输出了。
修改代码,将} else if ($event=='subscribe') { 这一行代码独立出来,然后在执行之前再次输出event变量,看看是什么妖怪:
再次执行代码,log输出结果如下:
event:subscribe:: are you ok,event:SCAN:
怎么会变成SCAN啦,再看一遍代码,终于找到原因了。
逻辑判断==和赋值语句=的区别
这是一个新手很容易犯的错误,没想到学哥也犯这种错误,反省1分钟。
第30行代码:
} else if ($event='SCAN' && $eventkey=='88') {
这里面的$event='SCAN'写错了,应该写成$event=='SCAN'。
==是逻辑判断语句,=是赋值语句。
本来$event的值是subscribe,走到这一行,$event被赋值为SCAN了,所以后面的判断就得不到预期的结果了。
至此,原因终于水落石出了。
这个错误产生的根源,学哥反思下来,应该还是代码没有整理好,因为其实从28行到31行代码,是在某次测试某个功能的时候添加的,但测试并没有全部覆盖到所有的情况,后来在实际应用中已经不用了,但是并没有从代码中删除,这就导致了没有经过充分测试的代码仍然留着,而后来学哥修改后面代码的时候,下意识的认为之前的代码是正确的,因此没有怀疑这段代码。
要假设任何代码都会出错
编写程序真的是一个需要严密逻辑的工作,需要有质疑一切,怀疑一切的精神,否则,真的很容易百思不得其解,很容易怀疑自己,怀疑人生。
如果你也爱好编程,有志于从事这个行业,那么欢迎来和学哥交流学习,共同提高。