调试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 相关文章推荐
BBS(php &amp; mysql)完整版(一)
Oct 09 PHP
php5.5中类级别的常量使用介绍
Oct 02 PHP
destoon二次开发常用数据库操作
Jun 21 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
Dec 24 PHP
合格的PHP程序员必备技能
Nov 13 PHP
WordPress中的shortcode短代码功能使用详解
May 17 PHP
PHP读书笔记整理_结构语句详解
Jul 01 PHP
php有效防止图片盗用、盗链的两种方法
Nov 01 PHP
php中引用符号(&amp;)的使用详细介绍
Dec 06 PHP
PHP批量删除jQuery操作
Jul 23 PHP
PHP长网址与短网址的实现方法
Oct 13 PHP
解决Laravel5.x的php artisan migrate数据库迁移创建操作报错SQLSTATE[42000]
Apr 06 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
英雄试炼之肉山谷—引领RPG新潮流
2020/04/20 DOTA
PHP 和 MySQL 基础教程(三)
2006/10/09 PHP
php 上传功能实例代码
2010/04/13 PHP
mcrypt启用 加密以及解密过程详细解析
2013/08/07 PHP
几个实用的PHP内置函数使用指南
2014/11/27 PHP
php中PDO方式实现数据库的增删改查
2015/05/17 PHP
laravel 实现上传图片到本地和前台访问示例
2019/10/21 PHP
laravel 解决paginate查询多个字段报错的问题
2019/10/22 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
面向对象继承实例(a如何继承b问题)(自写)
2013/07/01 Javascript
HTML页面滚动时获取离页面顶部的距离2种实现方法
2013/09/05 Javascript
JS实现文档加载完成后执行代码
2015/07/09 Javascript
jQuery中each()、find()和filter()等节点操作方法详解(推荐)
2016/05/25 Javascript
js只执行1次的函数示例
2016/07/20 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
BootStrap实现响应式布局导航栏折叠隐藏效果(在小屏幕、手机屏幕浏览时自动折叠隐藏)
2016/11/30 Javascript
Bootstrap 轮播(Carousel)插件
2016/12/26 Javascript
利用HTML5+Socket.io实现摇一摇控制PC端歌曲切换
2017/01/13 Javascript
Javascript 编码约定(编码规范)
2018/03/11 Javascript
JavaScript两种计时器的实例讲解
2019/01/31 Javascript
vue实现数据控制视图的原理解析
2020/01/07 Javascript
vue图片裁剪插件vue-cropper使用方法详解
2020/12/16 Vue.js
python采集博客中上传的QQ截图文件
2014/07/18 Python
python读取word文档的方法
2015/05/09 Python
Python用Bottle轻量级框架进行Web开发
2016/06/08 Python
对python内置map和six.moves.map的区别详解
2018/12/19 Python
python GUI库图形界面开发之PyQt5中QMainWindow, QWidget以及QDialog的区别和选择
2020/02/26 Python
python 制作简单的音乐播放器
2020/11/25 Python
西班牙灯具网上商店:Lampara.es
2018/06/05 全球购物
Nice Kicks网上商店:ShopNiceKicks.com
2018/12/25 全球购物
ALDO美国官网:加拿大女鞋品牌
2018/12/28 全球购物
个人委托书范本
2014/04/02 职场文书
答谢会策划方案
2014/05/12 职场文书
反对形式主义、官僚主义、享乐主义和奢靡之风整改措施
2014/09/17 职场文书
2015年资料员工作总结
2015/04/25 职场文书
python数据分析之单因素分析线性拟合及地理编码
2022/06/25 Python