调试PHP程序的多种方法介绍


Posted in PHP onNovember 06, 2014

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

一、PHP自带的调试功能

1、自带的报错功能

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

(1)开发环境

开发环境需要打开报错,以下是php.ini的配置项及其说明:

; This directive sets the error reporting level.

; Development Value: E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.)

error_reporting = E_ALL | E_STRICT
; This directive controls whether or not and where PHP will output errors,

; notices and warnings too. Error output is very useful during development.

; Development Value: On

display_errors = On

这样你在开发过程中,能第一时间发现错误。

即使是一个低等级的报错“Notice: Undefined variable: a in E:\phpspace\test.php on line 14”,但一个未定义的变量的使用往往暗藏着bug。

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

(2)生产环境

生产环境不能直接将错误输出,而是记入日志,以下是php.ini的配置项及其说明:

; It could be very dangerous in production environments.

; It's recommended that errors be logged on production servers rather than

; having the errors sent to STDOUT.

display_errors = Off
; Besides displaying errors, PHP can also log errors to locations such as a

; server-specific log, STDERR, or a location specified by the error_log

; directive found below. While errors should not be displayed on productions

; servers they should still be monitored and logging is a great way to do that.

; Production Value: On

log_errors = On
; Log errors to specified file.

error_log = /path/to/php_error.log

当然日志写到文件里只是一个选择,还有其他配置可参考手册。

生产环境是给客户提供服务的,你不可能在上面进行断点、打印输出等操作,所以日志是不错的选择。

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

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

其的作用是,将“@”放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉。

如果一个缺陷发生在这个表达式中,从PHP的输出中看不到任何错误,这增加了调试的难度。所以能不用则不用。

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

比如这行代码:

$fp = fsockopen(“www.example.com”, 80, $errno, $errstr, 30);

开发者调试时已经确定,$fp为空,连接失败,是这一行有问题,但是为什么连接失败?

函数是php自带的,无法进行更深入的调试。所以一般这样的函数(主要是网络通信类的),会自己提供调试参数:$errno和$errstr。你可以加一句:

if (!$fp) echo “$errstr ($errno)<br />\n”;

就能看到连接失败的原因了。

这些函数有: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),从中检查出程序的瓶颈所在。

PHP 相关文章推荐
基于mysql的论坛(2)
Oct 09 PHP
在PHP中养成7个面向对象的好习惯
Jan 28 PHP
ThinkPHP模板判断输出Empty标签用法详解
Jun 30 PHP
ThinkPHP中的create方法与自动令牌验证实例教程
Aug 22 PHP
举例详解PHP脚本的测试方法
Aug 05 PHP
php商品对比功能代码分享
Sep 24 PHP
php array_slice 取出数组中的一段序列实例
Nov 04 PHP
php实现保存周期为1天的购物车类
Jul 07 PHP
PHP实现正则匹配所有括号中的内容
Jun 22 PHP
PHP基于PDO扩展操作mysql数据库示例
Dec 24 PHP
ThinkPHP框架实现FTP图片上传功能示例
Apr 08 PHP
php array 转json及java 转换 json数据格式操作示例
Nov 13 PHP
php实现singleton()单例模式实例
Nov 06 #PHP
php使用session二维数组实例
Nov 06 #PHP
php函数serialize()与unserialize()用法实例
Nov 06 #PHP
php实现webservice实例
Nov 06 #PHP
php的dl函数用法实例
Nov 06 #PHP
PHP写日志的实现方法
Nov 05 #PHP
PHP实现UTF-8文件BOM自动检测与移除实例
Nov 05 #PHP
You might like
用PHP发电子邮件
2006/10/09 PHP
PHP 伪静态隐藏传递参数名的四种方法
2010/02/22 PHP
深入apache配置文件httpd.conf的部分参数说明
2013/06/28 PHP
php实现的Curl封装类Curl.class.php用法实例分析
2015/09/25 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
用Javascript同时提交多个Web表单的方法
2009/12/26 Javascript
javascript中IE浏览器不支持NEW DATE()带参数的解决方法
2012/03/01 Javascript
js实现通用的微信分享组件示例
2014/03/10 Javascript
网页实时显示服务器时间和javscript自运行时钟
2014/06/09 Javascript
JS实现字符串转日期并比较大小实例分析
2015/12/09 Javascript
javascript每日必学之封装
2016/02/23 Javascript
JQuery给select添加/删除节点的实现代码
2016/04/26 Javascript
微信小程序之电影影评小程序制作代码
2017/08/03 Javascript
简易Vue评论框架的实现(父组件的实现)
2018/01/08 Javascript
浏览器调试动态js脚本的方法(图解)
2018/01/19 Javascript
JS实现的哈夫曼编码示例【原始版与修改版】
2018/04/22 Javascript
js+canvas实现验证码功能
2020/09/21 Javascript
JavaScript模块管理的简单实现方式详解
2019/06/15 Javascript
python 异常处理总结
2016/10/18 Python
windows上安装Anaconda和python的教程详解
2017/03/28 Python
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
django项目简单调取百度翻译接口的方法
2019/08/06 Python
Pytorch实现将模型的所有参数的梯度清0
2020/06/24 Python
python实现画图工具
2020/08/27 Python
Selenium结合BeautifulSoup4编写简单的python爬虫
2020/11/06 Python
Static Nested Class 和 Inner Class的不同
2013/11/28 面试题
求职简历的自我评价怎样写好
2013/10/07 职场文书
商务日语毕业生自荐信
2013/11/23 职场文书
培训讲师岗位职责
2014/04/13 职场文书
“六查”、“三学”、“三干”查摆问题整改措施
2014/09/27 职场文书
井冈山红色之旅感想
2014/10/07 职场文书
学校纪律作风整改措施思想汇报
2014/10/11 职场文书
产品质量保证书范本
2015/02/27 职场文书
律师函格式范本
2015/05/27 职场文书
python数据可视化使用pyfinance分析证券收益示例详解
2021/11/20 Python
铁拳制作人赞《铁拳7》老头环Mod:制作精良 但别弄了
2022/04/03 其他游戏