如何调试PHP

bbfs-no-bug-logo

调试的定义:通过一定方法,在程序中找到并减少缺陷的数量,从而使其能正常工作。这里说一些如何调试PHP程序的经验,有经验的同学可直接略过。
一、PHP自带的调试功能

1、自带的报错功能

两个名词:开发环境是开发人员在进行开发和调试的环境,生产环境是最终客户在用的线上环境。开发环境和生产环境要分开设置报错功能。

(1)开发环境

开发环境需要打开报错,需要设置php.ini的项:error_reporting display_errors。这样你在开发过程中,能第一时间发现错误。即使是一个低等级的报错“Notice: Undefined variable”,但一个未定义的变量的使用往往暗藏着bug。

你会问,如果我引进了开源的类库,他们抛出一堆的低等级错误怎么办?一般代码质量好的类库,也没有“Notice”级别的报错的。所以这也是鉴别一个类库质量的方法。

(2)生产环境

生产环境不能直接将错误输出,而是记入日志,需要设置php.ini的项:display_errors log_errors error_log。日志可以写到文件或其他地方,可参考手册。生产环境是给客户提供服务的,你不可能在上面进行断点、打印输出等操作,所以日志是不错的选择。

2、其他一些语言特性、功能的使用

(1)少用错误控制运算符“@”

其的作用是,将“@”放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉。如果一个缺陷发生在这个表达式中,从PHP的输出中看不到任何错误,这增加了调试的难度。所以能不用则不用。

(2)有些函数自带有debug功能

比如这行代码:$fp = fsockopen(“www.example.com”, 80, $errno, $errstr, 30);

开发者调试时已经确定,$fp为空,连接失败,是这一行有问题,但是为什么连接失败?函数是php自带的,无法进行更深入的调试。所以一般这样的函数(主要是网络通信类的),会自己提供调试参数:$errno和$errstr。只要把他们打印出来就能看到连接失败的原因了。

这些函数有:fsockopen,pfsockopen,stream_socket_server,stream_socket_client 等。还有些函数是调试一个功能用的,比如:mysql_errno,socket_last_error,socket_strerror 等。这些只需要了解下,碰到能想到用即可。
二、引进调试工具

在遇到复杂问题时,可以借助调试工具。比较成熟的有Xdebug、ZendDebugger。以Xdebug为例,它能够:控制打印输出的样式和数组层级、堆栈式的追踪错误、追踪函数调用、代码执行覆盖分析、程序的概要分析(Profiling)、远程调试。详见:http://xdebug.org/docs/。Xdebug前两个功能是对PHP原有的调试功能做了改进,更方便调试。

复杂的问题,调试不出来的,可能是业务上的的问题,下面也有说业务逻辑的调试。
三、调试业务逻辑错误

当PHP脚本跑起来,没有任何错误,只能说它没有语法上的错误,但是不能说明它业务逻辑上没错误。很多业务逻辑的错误并不会反映在语法错误上,但调试的思路和PHP自带调试功能差不多。

下面是一些方法。

1、最基本的调试方法

先确定两个东西:程序预期的结果、程序现在的不符合预期的结果;寻找与两种结果相关的代码片段;阅读这些代码片段,尝试以“肉眼”找出错误;找不出,则需要输出一些关键变量,通过检查它们的值是否正确来判断是哪里发生了错误;若干次尝试,最终你可以确定错误发生在哪个点。

你也可以借助Xdebug等工具,查看变量值的变化,或者设置断点进行调试。

2、记录运行日志

有些复杂或特殊的业务,用上面的方法不合适,比如:一个不能被打断的后台运行脚本。这些情况下记录运行日志比较合适。记日志的点要有所选择,除了业务上比较重要的点,通常容易出错的地方有:网络连接和通信、系统权限问题等。

3、单元测试

以代码测试代码,而不是像第一点一样调试完会把测试代码丢掉。以测试驱动开发。这个话题比较大,但适合放这里提一下。有兴趣的同学可以去了解。
四、调试非功能性的错误

非功能性错误,比如:内存溢出导致程序挂掉了、效率有问题导致程序非常慢、死循环了等等。这些问题,用“肉眼”检查代码效率太低了。所以可以借助调试工具做程序的概要分析(Profiling),从中检查出程序的瓶颈所在。
这是对我之前的文章的整理,原文在 http://www.howzhi.com/group/php/discuss/468。将此URL拷贝到电脑的方法:将该文章用浏览器打开(微信文章详情中,右上选项按钮点开),在浏览器中能选择复制字符串,将微信在网页端登录,将拷贝的URL通过文件传输助手传给网页端。

另外每篇文章期待大家的意见,请直接回复。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">