大家都知道在开发过程中,代码的调试非常重要,对于一些常见错误的调试技巧有助于提高代码编写的效率。

本文介绍调试PHP应用程序的各种方法,包括在Apache and PHP中打开错误报告,以及通过在一个简单的PHP脚本中放置策略性的print语句,找到更困难的bug的源头。

还会介绍用于Eclipse的PHPEclipse插件,这是一个灵活的开发环境,具有实时语法解析能力,还会介绍PHPEclipse的DBG调试器扩展。

简介

有许多PHP调试技术可以在编码的时候节约大量时间。一个有效却很基本的调试技术就是打开错误报告。另一个略微高级一点的技术包括使用print语句,通过显示在屏幕上实际出现的内容,有助于精确地找出更难发现的bug。

PHPEclipse是一个Eclipse插件,能够强调常见的语法错误,可以与调试器结合起来用于设置断点。

设置

要学习本文描述的概念,需要PHP、Web服务器和Eclipse。调试器扩展支持的PHP版本是V5.0.3。

我们需要一个Web服务器来解析用PHP创建的页面并把它们显示到浏览器。

本文中使用的是Apache2。但是,任何Web服务器都可以满足要求。

要利用本文中介绍的一些调试技术,需要安装Eclipse V3.1.1和插件PHPEclipse V1.1.8。由于Eclipse要求Java?技术,所以还要下载它。

还需要PHP的调试器扩展模块。安装它略有些麻烦。请仔细跟随安装调试器扩展的操作说明。现在,先在php.ini文件中注释掉那些要求装入和配置PHP扩展的行。在需要使用调试器的时候,再取消注释。

请参阅参考资料(文章后附)获得下载信息。现在介绍出错消息。

出错消息

出错消息是作为开发人员的第一道防线。谁都不想在一台没有配置成显示出错消息的服务器上用PHP开发代码。

但是,请记住,当代码调试完成,准备运行的时候,应当确保关闭了错误报告,因为不希望站点的访问者看到出错消息,这会给他们提供足够的信息来利用站点的弱点并黑掉站点。

也可以用出错消息为自己服务,因为它们会显示抛出或生成错误的正确代码行。这样,调试就变成在浏览器上查看生成的错误所显示的行号,并在代码中检查这一行。

稍后,将会看到PHPEclipse插件通过即时地给语法错误加下划线并在保存文件时用红色“x”标注语法错误,可在开发和调试过程中提供极大的帮助。

先来看如何在php.ini文件中开启错误报告并设置错误报告的级别。然后将学习如何在Apache的配置文件中覆盖这些设置。

PHP的错误报告

php.ini文件中有许多配置设置。您应当已经设置好自己的php.ini文件并把它放在合适的目录中,就像在Linux上安装PHP和Apache 2的文档说明中所示的那样(请参阅参考资料)。

在调试PHP应用程序时,应当知道两个配置变量。下面是这两个变量及其默认值:

  display_errors = Off error_reporting = E_ALL

通过在php.ini文件中搜索它们,可以发现这两个变量当前的默认值。

display_errors变量的目的很明显——它告诉PHP是否显示错误。

默认值是Off。但是,要让开发过程更加轻松,请把这个值设为On:

  display_errors = On

error_reporting变量的默认值是E_ALL。这个设置会显示从不良编码实践到无害提示到出错的所有信息。

E_ALL对于开发过程来说有点太细,因为它在屏幕上为一些小事(例如变量未初始化)也显示提示,会搞糟浏览器的输出。

我只想看到错误和不良编码实践,但是不想看到无害的提示。所以,请用以下值代替error_reporting的默认值:

  error_reporting = E_ALL & ~E_NOTICE

重新启动Apache,就全部设置好了。接下来,将学习如何在 Apache 上做同样的事。

服务器上的错误报告

依赖于Apache正在做的工作,在PHP中打开错误报告可能没法工作,因为在计算机上可能有多个PHP版本。有时很难区分Apache正在使用哪个PHP版本,因为Apache只能查看一个php.ini文件。

不知道Apache正在使用哪个php.ini文件配置自己是一个安全问题。但是,有一种方法可以在Apache中配置PHP变量,从而保证设置了正确的出错级别。

而且,最好知道如何在服务器端设置这些配置变量,以否决或抢占php.ini文件,从而提供更高级别的安全性。

在配置Apache时,应该已经接触过<apache2-install-dir>/conf/httpd.conf 中 http.conf 文件中的基本配置。

要做在php.ini文件中已经做过的事,请把下列各行添加到httpd.conf,覆盖任何php.ini文件:

  php_flag display_errors on php_value error_reporting 2039

这会覆盖在php.ini文件中为display_errors已经设置的标志,以及error_reporting 的值。

值2039代表E_ALL & ~E_NOTICE。如果愿意采用E_ALL,请把值设为2047。同样,还是要重启Apache。

接下来,要在服务器上测试错误报告。

测试错误报告

如果启动了错误报告,会节约许多时间。PHP 中的错误会指向代码中的错误。请创建一个简单的PHP文件test.php,并像清单1所示一样定义它。

清单1. 一个生成错误的简单PHP

  <?php print("The next line generates an error.<br>"); printaline("PLEASE?"); print("This will not be displayed due to the above error."); ?>

第一个print()语句会向Web浏览器显示它的内容。但是第二个语句会生成错误并在Web页面上显示。

这造成最后一个print()语句不起作用,如图1所示。

图1. 生成错误

  

现在开启了错误报告!接下来,用print语句帮助调试应用程序。

介绍print语句

因为应用程序中的功能性bug不会产生错误,所以在所有调试策略中,关于如何正确地放置和使用print或die语句来调试PHP应用程序的知识是一种很好的资产。

可以用print语句在代码中缩小对问题语句的定位,这些语句在语法上没有错误,也不是bug,但是从代码的功能上看是bug。

这些是最难发现和调试的bug,因为它们不会抛出错误。惟一知道的就是在浏览器上显示的内容不是想要的内容,或者想要保存在数据库中的内容根本没有保存。

假设正在处理通过GET请求发送过来的表单数据,想向浏览器显示信息,但是出于某种原因,数据没有正确地提交,或者不能正确地从GET请求中读出。

要调试这类问题,重要的是用print()或die()语句知道变量的值是什么。

die()语句会中止程序执行,并在Web浏览器上显示文本。如果不想注释掉代码,而且只想显示到出错之前的信息和出错信息,不想显示后面的信息,那么die()语句特别有用。

让我们在PHP中用print语句来测试这个概念

使用print语句进行调试。

在我做程序员的那些时候,当我在Linux®上开发应用程序时,没有方便的GUI可以告诉我 bug在哪,我迅速地发现我在程序中放的print语句越多,我在应用程序中把bug的范围缩小到一行的机会越大。

请创建另一个PHP文件test2.php,并像清单2所示的那样定义它。

清单2. 显示通过 GET 提交的所有变量

  <?php $j = ""; print("Lets retrieve all the variables submitted to this "); print(" via a GET request:<br>"); foreach($_GET as $key => $i){ print("$key=$j<br>"); } if($_GET['Submit'] == "Send GET Request") $j = "done!<br>"; ?> <form method="GET"> Name: <input name="name"><br> Email: <input name="email" size="25"><br> <input name="Submit" type="submit" value="Send GET Request"> </form>

您可能会非常容易地发现清单2中的bug!您很棒!但请注意这是一个非常简单的脚本,只是作为使用print语句进行调试而展示的一个例子而已。

这个脚本只是提取GET请求中的所有变量,如果有,就把它们显示在浏览器上。还提供了一个表单,用GET请求向服务器发送变量以进行测试。请看输出,如图2所示。

图2. test2.php的输出

  

现在单击Send GET Request按钮,请注意只有$_GET请求的键显示在浏览器上,而正确的值都没显示。

可以在循环中放一个print语句,检验在foreach循环中每个元素中是否确实存在数据。请参阅清单3。

清单3. 用print语句验证代码的功能

  ... foreach($_GET as $key => $i){ print("Correct data? " . $_GET[$key] . "<br>"); print("$key=$j<br>"); } ...

放进去的print语句是粗体。

注意,现在已经知道在Web浏览器上显示的$key值是正确的,但是由于某些原因,值没有正确地显示。请看新的输出,如图3所示。

图3. 修改后的test2.php的输出

  

现在已经知道应用程序正确地从GET请求接收到了变量,那么肯定是在代码中有bug。

查看之后注意到,用来显示值的变量$j是错误的。在foreach语句中指定的是$i,所以它肯定会有正确的值,但是无意之中输入了$j。所以通过把$j替换成$i,迅速地修正了错误,重新载入页面之后,就看到了正确的输出,如图4所示。

图4. 修正后的test2.php的输出

  

现在可以删除或注释掉刚才添加的print语句了,因为已经发现了代码中的bug。

注意,这只是在调试应用程序时可能遇到的许多错误中的一个很小的子集。对于使用数据库时可能遇到的问题,一个好的解决方案是输出SQL语句,以确保执行的SQL就是想要执行的。

现在要来看看如何使用Eclipse IDE和PHPEclipse插件及调试器扩展进一步在调试历程中提供帮助。

使用PHPEclipse

您可能用过Eclipse,但是可能不熟悉它。请参阅参考资料获得Eclipse平台的介绍。

用于Eclipse的PHPEclipse插件是用来开发PHP应用程序的一个流行工具。请启动Eclipse并把工作区目录指定为Apache的www目录(在我的机器上是 c:www)。现在单击File>New>Project。

会弹出New Project向导。双击PHP文件夹并选择PHP Project。单击Next,输入项目名称debugArticle,并单击Finish。

如果把Web服务器设置为在端口80上侦听,那么不需要做任何修改。否则,请转到Navigator窗口,在PHP项目debugArticle上右击,选择Properties,然后单击PHP Project Settings。

单击Configure Workspace Settings然后修改合适的localhost或者添加Web服务器侦听的端口(例如https://localhost:8080)。单击Apply完成设置。

Navigator窗口应当显示项目和一个.project文件。在项目上右击,就像前面做的那样,只是这次选择New>PHP File。

用想要创建的PHP文件的名称test3.php替换*.php,然后单击Finish。在Eclipse IDE中应当出现一个新文件。可能需要导航到窗口底部的PHP浏览器来查看PHP文件的当前输出(参见图5)。

图5. Eclipse的PHPEclipse插件

  

注意,只有Windows®的用户可以像清单5所示的那样使用PHP浏览器。通过打开独立浏览器窗口并把浏览器指向测试脚本所在目录,也可以使用同样的功能。

现在来演示这个应用程序,证明它的强大能力。

在“使用调试器”一节中,将学习如何用Eclipse、PHPEclipse和前面下载的调试器PHP扩展来调试PHP应用程序。先从学习如何使用它的语法解析功能开始。

语法解析和加下划线

先从查看PHPEclipse如何提供帮助调试PHP应用程序的实时语法解析功能开始。要看这个特性的实际应用,先从在Eclipse中定义test3.php开始,如下所示。

  <?phpprint(,"Hello World!");?>

注意,在清单4中加下划线的两个字符在Eclipse中加了下划线,提示语法不正确。按Ctrl+S保存文件,会在Eclipse中显示解析错误:在代码中与解析错误对应的行上会加上红“x”,如图6所示。

图6. 语法错误强调

  

现在演示PHP浏览器。这个窗口提供了当前PHP脚本的预览,如图6所示。

从上面定义的test3.php中删除逗号(,)。按Ctrl+S保存文件,然后观察PHP浏览器窗口的更新,显示了Hello World(参见图7)。

图7. 在PHPEclipse中预览PHP脚本

  

下面是用调试器在 PHP 中设置断点。

使用调试器

使用调试器,可以设置断点并查看PHP代码到所设断点之前的浏览器输出。

然后可以继续代码的执行并查看到下一断点之前的浏览器输出,然后再到下一个,直到PHP脚本完成。

现在把“设置”一节中在php.ini中注释掉的行取消注释,并重新启动Apache。现在装入了调试器,Eclipse能够和它挂上了。

现在在Eclipse中设计调试环境。请创建新的test4.php文件,先保持为空。

现在单击Run>Debug。在左侧面板中选择PHP DBG ,并单击New。现在转到File选项卡,输入当前项目debugArticle以及想要调试的文件test4.php。

现在转到Environment选项卡,然后再到Interpreter子选项卡。在PHP的安装目录中找到php.exe文件(我的是c:appsphp5.0.3php.exe)。

现在单击Remote Debug子选项卡,选择Remote Debug,如果没有使用Windows,请取消“Open with DBGSession URL in internal browser box”复选框。

把Remote Source路径设置成与要测试的PHP脚本的绝对路径(不是Web路径)相同(我的设置是c:wwwdebugArticletest4.php)。现在单击 Debug。

现在应当装入Debug透视图,如图8所示。否则,请单击Window>Open Perspective>Other,并选择Debug。

图8. Eclipse中的Debug透视图

  

现在可以设置断点了。

对于本文中使用的插件和扩展的版本,断点功能是必需的,因为PHP在把输出发送到浏览器之前会缓冲它。

除此之外,需要做的不仅仅是设置一个断点把当前显示数据刷新到Web浏览器,所以要像下面和图8所示那样定义test4.php。

清单4. 设置和创建断点

  <?phpfunction break-point(){ ob_flush(); flush(); sleep(.1); debugBreak();}print("This will get shown first, ");print("as will this<br>");breakpoint();print("This won't get shown until after ");print("continuing the break-point<br>");breakpoint();print("END!");?

breakpoint()函数会把缓冲的输出和其他缓冲的数据刷新到Web浏览器。

对sleep(.1)的调用是必需的,这样代码中止于debugBreak()之前,服务器才有足够的时间把数据刷新到Web浏览器,这个函数是前面下载的PHP调试器扩展的内部函数。

这样,调用breakpoint()会把HTML块、print()和echo()语句的数据刷新到浏览器,然后中止代码执行。

在像清单4那样编写完代码之后,可以打开浏览器并指向test4.php,或者可以查看PHP浏览器窗口(我的是https://localhost/debugArticle/test4.php)。

每次输入和保存文件时,在PHP浏览器窗口中就已经启动了调试序列。如果不使用Windows,请通过浏览器查看test4.php。

在保存了文件之后,用F8或单击Run>Resume继续代码执行。持续这么做,直到最后一行输出是END!为止(参见图9、10和11)。

图9. 初始的到第一个断点的PHP浏览器输出

  

请注意图9中的Debug窗口如何把执行显示为挂起的。

图10. 第一个断点之后到第二个断点之前的PHP浏览器输出

  

图10的Debug窗口仍然把执行显示为挂起,而第二组数据显示在PHP浏览器中。

图11. 完整的PHP浏览器输出

  

注意,图11的Debug窗口中的代码不再挂起,整个脚本已经执行,如图11中的PHP浏览器所示。

既然已经看到了用PHPEclipse和调试器扩展进行开发的优势,那么很难想像没有它会怎么样。

结束语

现在已经向PHP的调试技术集中添加了错误报告的运用、print语句、PHPEclipse和调试器扩展,您可以通过减少每行代码的错误数量,成为更有效的 PHP 编码人员。

请参阅参考资料获得一些PHP教程,可以在上面测试这些新技能。

下载Sample code for PHP Debugging

参考资料

学习

您可以参阅本文在developerWorks全球站点上的 英文原文。

学习如何在基于Windows和UNIX®的系统上安装Java。

请访问Eclipse.org获得编程和如何使用它的全面信息。

“Eclipse平台入门”(developerWorks,2002年11月)提供了Eclipse的历史和概述,包括如何安装Eclipse和插件的细节。

请访问PHPEclipse学习关于安装PHPEclipse和如何使用它的更多内容。

DBG是一个全功能的PHP调试器引擎,一个交互的工具,有助于调试PHP脚本。请阅读Installing and configuring the debugger上的这份教程。

要学习关于Eclipse的更多内容,请访问developerWorks的Eclipse project resources。

要学习关于PHP的更多内容,请访问developerWorks的PHP project resources。

请参阅PHP手册获得更多关于error reporting的内容。

请阅读安装PHP and Apache2 on Linux的操作说明。

请阅读安装PHP and Apache2 on Windows的操作说明。

要获得一系列学习PHP编程的developerWorks教程,请参阅“学习PHP,第1部分”、学习PHP,第2部分 和学习PHP,第3部分。

请密切关注developerWorks technical events and webcasts。

请访问developerWorks开放源码专区获得丰富的how-to信息、工具和项目更新,有助于用开放源码技术进行开发并把它们用于 IBM 的产品。

获得产品和技术

请从PHP.net下载最新版本的PHP。

请下载最新版本的Apache2。

请从Sun公司下载Java技术。

请从Eclipse.org下载最新版本的Eclipse。

请从Sourceforge下载PHPEclipse。把Eclipse解压到eclipse-install-dir,然后把PHPEclipse解压到eclipse-install-dir。

在安装扩展时,要按照PHPEclipse instructions。但是,在要求在php.ini文件中装入和配置PHP扩展的地方注释掉那些行。在准备使用调试器时再取消这些行的注释。

订购免费的SEK for Linux,这套DVD(两张),包含了来自DB2®、Lotus®、 Rational®、Tivoli®和WebSphere®的用于Linux的最新IBM试用软件。

请用IBM试用软件 改造您的下一个开放源码开发项目,可以下载也可以通过DVD 得到。

讨论

通过参与developerWorks blogs加入developerWorks社区。

关于作者

Tyler Anderson2004年从Brigham Young大学毕业,获得计算机科学学位。现在是他作为计算机工程硕士生的最后一学期。过去,他作为数据库程序员为DPMG.com工作,现在他是位于Beaverton, Ore的Stexar公司的工程师。

原文地址:

https://www.ibm.com/developerworks/cn/opensource/os-debug/