你如何调试PHP脚本?

你如何调试PHP脚本?

我知道基本的调试,如使用错误报告。 PHPEclipse中的断点调试也非常有用。

在phpStorm或任何其他IDE中进行调试的最佳方法是什么(就快速而简单而言)?

尝试使用Eclipse PDT来设置具有像您所提到的调试功能的Eclipse环境。 进入代码的能力是更好的方法来调试var_dump的旧方法,并在各个点上打印以查看流程出错的位置。 当所有其他都失败了,而我所有的是SSH和VIM我仍然var_dump() / die()找到代码向南。

你可以使用Firephp作为firebug的一个附件来在与javascript相同的环境下调试php。

我也使用前面提到的Xdebug来分析php。

这是我的小调试环境:

 error_reporting(-1); assert_options(ASSERT_ACTIVE, 1); assert_options(ASSERT_WARNING, 0); assert_options(ASSERT_BAIL, 0); assert_options(ASSERT_QUIET_EVAL, 0); assert_options(ASSERT_CALLBACK, 'assert_callcack'); set_error_handler('error_handler'); set_exception_handler('exception_handler'); register_shutdown_function('shutdown_handler'); function assert_callcack($file, $line, $message) { throw new Customizable_Exception($message, null, $file, $line); } function error_handler($errno, $error, $file, $line, $vars) { if ($errno === 0 || ($errno & error_reporting()) === 0) { return; } throw new Customizable_Exception($error, $errno, $file, $line); } function exception_handler(Exception $e) { // Do what ever! echo '<pre>', print_r($e, true), '</pre>'; exit; } function shutdown_handler() { try { if (null !== $error = error_get_last()) { throw new Customizable_Exception($error['message'], $error['type'], $error['file'], $error['line']); } } catch (Exception $e) { exception_handler($e); } } class Customizable_Exception extends Exception { public function __construct($message = null, $code = null, $file = null, $line = null) { if ($code === null) { parent::__construct($message); } else { parent::__construct($message, $code); } if ($file !== null) { $this->file = $file; } if ($line !== null) { $this->line = $line; } } } 

Xdebug和用于Notepad ++的DBGp插件,用于重型bug查找,FirePHP用于轻量级。 又快又脏? 没有什么比dBug 。

XDebug对于开发至关重要。 我在任何其他扩展之前安装它。 它为您提供任何错误的堆栈跟踪,并且可以轻松启用分析。

要快速查看数据结构,请使用var_dump() 。 不要使用print_r()因为你必须用<pre>包围它,并且它一次只打印一个var。

 <?php var_dump(__FILE__, __LINE__, $_REQUEST); ?> 

对于一个真正的调试环境,我发现最好的是Komodo IDE,但是它的成本是$$。

PhpEd非常好。 你可以进入/超出/退出功能。 您可以运行专门的代码,检查变量,更改变量。 这太神奇了。

1)我使用print_r()。 在TextMate中,我有一个“pre”的代码片段,它展开为:

 echo "<pre>"; print_r(); echo "</pre>"; 

2)我使用Xdebug,但一直没有能够让我的Mac上的GUI正常工作。 它至少打印出可读的堆栈跟踪版本。

我已经使用了Zend Studio(5.5)和Zend Platform 。 这就给出了适当的调试,断点/步进代码等,虽然在一个价格。

诚实地说,将print和print_r()组合在一起打印出变量。 我知道很多人喜欢使用其他更高级的方法,但我觉得这是最容易使用的。

我会说,直到我在Uni进行了一些微处理器编程,我才完全理解这一点,甚至无法使用。

Derick Rethans的Xdebug非常好。 我前一段时间使用它,发现它不是很容易安装。 一旦你完成了,你不会明白你没有它如何管理:-)

在Zend Developer Zone上有一篇很好的文章(在Linux上安装似乎并不容易),甚至还有一个我从未使用过的Firefox插件 。

我使用Netbeans与XDebug。 在网站上查看如何配置文档。 http://php.netbeans.org/

我使用Netbeans XDebug和Easy XDebug FireFox插件

当你调试MVC项目时,附加组件是必不可少的,因为在Netbeans中运行XDebug的正常方式是通过url注册dbug会话。 通过在FireFox中安装的插件,您可以设置您的Netbeans项目属性 – >运行配置 – >高级,然后选择“不打开Web浏览器”您现在可以像往常一样使用Ctrl-F5设置断点并开始调试会话。 打开FireFox并右键单击右下角的附加图标开始监视断点。 当代码到达断点时,它将停止,你可以检查你的变量状态和调用堆栈。

输出缓冲是非常有用的,如果你不想搞乱你的输出。 我可以随意发表评论/取消评论

  ob_start();var_dump(); user_error(ob_get_contents()); ob_get_clean(); 

PhpEdit有一个内置的调试器,但我通常最终使用echo(); 和print_r(); 老式的方式!

对于使用print_r / echo来计算出我使用我的IDE(PhpEd)调试功能来说花费太多时间的问题。 不像其他我用过的IDE,PhpEd几乎不需要安装。 我不用它来解决我遇到的任何问题的唯一原因是它太痛苦了 。 我不确定缓慢是特定于PhpEd或任何PHP调试器。 PhpEd不是免费的,但我相信它使用了一个开源的调试器(如前面提到的XDebug)。 PhpEd的好处是,它不需要过去我发现真的非常乏味的设置。

手动调试通常对我来说更快 – var_dump()debug_print_backtrace()是您用来设置逻辑的所有工具。

那么,在某种程度上,这取决于事情正在向南。 这是我尝试隔离的第一件事,然后根据需要使用echo / print_r()。

注意:你们知道你可以将print_r()的第二个参数传给true,它会返回输出而不是打印输出。 例如:

 echo "<pre>".print_r($var, true)."</pre>"; 

当Rails不可用时,我经常使用CakePHP。 为了调试错误,我通常在tmp文件夹中找到error.log ,并用命令在终端中找到它。

 tail -f app/tmp/logs/error.log 

它给了你从正在发生的事情的蛋糕运行对话,这是非常方便的,如果你想输出的东西,你可以使用中间代码。

 $this->log('xxxx'); 

这通常可以让你很清楚发生了什么事情。

print_r(debug_backtrace());

或类似的东西 :-)

Komodo IDE可以和xdebug一起使用,即使是重新调试也是如此。 它需要最少量的配置。 所有你需要的是一个PHP的版本,Komodo可以在本地使用一个断点上的代码。 如果你已经将脚本导入到了komodo项目中,那么你可以通过鼠标单击来设置断点,你将如何在eclipse中设置它来调试java程序。 远程调试显然比使用本地调试设置(如果您位于MAC或Linux桌面上,可以非常容易地配置)要正确地工作(您可能必须在工作区中使用php脚本映射远程URL)更为棘手。

Nusphere也是一个很好的php nusphere调试器

有许多PHP的调试技术,可以节省你无数个小时编码。 一个有效的,但基本的调试技术是简单地打开错误报告。 另一个稍微更先进的技术是使用打印语句,通过显示屏幕上实际显示的内容,可以帮助找出更难以捉摸的错误。 PHPeclipse是一个Eclipse插件,可以突出常见的语法错误,并可以与调试器一起使用来设置断点。

 display_errors = Off error_reporting = E_ALL display_errors = On 

也用了

 error_log(); console_log(); 

为print_r()+1。 用它来转储对象或变量的内容。 为了使其更具可读性,请使用预标签来完成,因此您无需查看源代码。

 echo '<pre>'; print_r($arrayOrObject); 

还var_dump($东西) – 这是非常有用的看到的亚型的类型

在生产环境中,我使用error_log()将相关数据记录到服务器的错误日志中。

我使用zend工作室与内置调试器的日食。 与使用xdebug进行eclipse pdt调试相比,它仍然很慢。 希望他们能解决这些问题,速度比最近的发布有所提高,但是仍然需要2-3秒的时间才能完成。 zend firefox工具栏真的让事情变得简单(调试下一页,当前页面等)。 此外,它还提供了一个分析器,可以对您的代码进行基准测试,并提供饼图,执行时间等。

大部分的错误都可以通过var_dump关键变量轻松找到,但显然取决于您开发的应用程序类型。

对于更复杂的算法,step / breakpoint / watch函数非常有用(如果不是必要的话)

PHP的DBG

交互式Stepper PHP调试器作为一个SAPI模块实现,可以让您完全控制环境,而不会影响代码的功能或性能。 它的目标是成为一个轻量级,功能强大,易于使用的PHP 5.4+调试平台,并且是PHP 5.6开箱即用的。

功能包括:

  • 逐步调试
  • 灵活的断点(类方法,函数,文件:行,地址,操作码)
  • 使用内置的eval()轻松访问PHP
  • 轻松访问当前执行的代码
  • 用户级API
  • SAPI不可知论 – 易于集成
  • PHP配置文件支持
  • JIT超级全球 – 设置您自己的!
  • 可选readline支持 – 舒适的终端操作
  • 远程调试支持 – 捆绑的Java GUI
  • 操作简单

看截图:

PHP的DBG  - 逐步调试 - 截图

PHP的DBG  - 逐步调试 - 截图

主页: http : //phpdbg.com/

PHP错误 – 更好的PHP错误报告

这是很容易使用库(实际上是一个文件)来调试您的PHP脚本。

你需要做的唯一事情就是包含一个文件,如下所示(在你的代码的开头):

 require('php_error.php'); \php_error\reportErrors(); 

那么所有的错误都会给你提供诸如回溯,代码上下文,函数参数,服务器变量等信息。例如:

PHP错误|改进PHP的错误报告 - 回溯的截图 PHP错误|改进PHP的错误报告 - 回溯的截图 PHP错误|改进PHP的错误报告 - 回溯的截图

功能包括:

  • 微不足道的使用,它只是一个文件
  • 在浏览器中显示正常和ajaxy请求的错误
  • AJAX请求暂停,允许您自动重新运行它们
  • 尽可能严格地制造错误(鼓励代码质量,并趋于提高性能)
  • 整个堆栈跟踪中的代码片段
  • 提供更多信息(如全功能签名)
  • 修复了一些错误信息,这些信息都是错误的
  • 语法高亮
  • 看起来漂亮!
  • 定制
  • 手动打开和关闭它
  • 运行没有错误报告的特定部分
  • 忽略允许您避免在堆栈跟踪中突出显示代码的文件
  • 应用程序文件 错误发生时,这些优先级!

主页: http : //phperror.net/

GitHub: https : //github.com/JosephLenton/PHP-Error

我的叉(有额外的修复): https : //github.com/kenorb-contrib/PHP-Error

DTrace的

如果您的系统支持DTrace动态跟踪 (在OS X上默认安装),并且您的PHP是在默认情况下启用DTrace探测器( --enable-dtrace )的情况下编译的,那么此命令可以帮助您在没有时间的情况下调试PHP脚本:

 sudo dtrace -qn 'php*:::function-entry { printf("%Y: PHP function-entry:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); }' 

所以鉴于以下别名已被添加到您的rc文件(例如~/.bashrc~/.bash_aliases ):

 alias trace-php='sudo dtrace -qn "php*:::function-entry { printf(\"%Y: PHP function-entry:\t%s%s%s() in %s:%d\n\", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); }"' 

你可以跟踪你的脚本,很容易记住别名: trace-php

这里是更先进的dtrace脚本,只需将其保存到dtruss-php.d ,使其可执行( chmod +x dtruss-php.d )并运行:

 #!/usr/sbin/dtrace -Zs # See: https://github.com/kenorb/dtruss-lamp/blob/master/dtruss-php.d #pragma D option quiet php*:::compile-file-entry { printf("%Y: PHP compile-file-entry:\t%s (%s)\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1)); } php*:::compile-file-return { printf("%Y: PHP compile-file-return:\t%s (%s)\n", walltimestamp, basename(copyinstr(arg0)), basename(copyinstr(arg1))); } php*:::error { printf("%Y: PHP error message:\t%s in %s:%d\n", walltimestamp, copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); } php*:::exception-caught { printf("%Y: PHP exception-caught:\t%s\n", walltimestamp, copyinstr(arg0)); } php*:::exception-thrown { printf("%Y: PHP exception-thrown:\t%s\n", walltimestamp, copyinstr(arg0)); } php*:::execute-entry { printf("%Y: PHP execute-entry:\t%s:%d\n", walltimestamp, basename(copyinstr(arg0)), (int)arg1); } php*:::execute-return { printf("%Y: PHP execute-return:\t%s:%d\n", walltimestamp, basename(copyinstr(arg0)), (int)arg1); } php*:::function-entry { printf("%Y: PHP function-entry:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); } php*:::function-return { printf("%Y: PHP function-return:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); } php*:::request-shutdown { printf("%Y: PHP request-shutdown:\t%s at %s via %s\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1), copyinstr(arg2)); } php*:::request-startup { printf("%Y, PHP request-startup:\t%s at %s via %s\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1), copyinstr(arg2)); } 

主页:GitHub上的dtruss-lamp

这里是简单的用法:

  1. 运行: sudo dtruss-php.d
  2. 在另一个终端上运行: php -r "phpinfo();"

为了测试,你可以去index.php任何文件根目录并运行PHP内置服务器:

 php -S localhost:8080 

之后,您可以通过http:// localhost:8080 / (或者选择任何适合您的端口)访问该站点。 从那里访问一些页面来查看跟踪输出。

注意:默认情况下,Dtrace在OS X上是可用的,在Linux上你可能需要dtrace4linux或者检查其他的选择 。

请参阅:在php.net上使用PHP和DTrace


SystemTap的

或者通过安装SystemTap SDT开发包(例如yum install systemtap-sdt-devel )检查SystemTap跟踪。

下面是一个示例脚本( all_probes.stp ),用于在SystemTap运行的PHP脚本的整个持续时间内跟踪所有核心PHP静态探测点:

 probe process("sapi/cli/php").provider("php").mark("compile__file__entry") { printf("Probe compile__file__entry\n"); printf(" compile_file %s\n", user_string($arg1)); printf(" compile_file_translated %s\n", user_string($arg2)); } probe process("sapi/cli/php").provider("php").mark("compile__file__return") { printf("Probe compile__file__return\n"); printf(" compile_file %s\n", user_string($arg1)); printf(" compile_file_translated %s\n", user_string($arg2)); } probe process("sapi/cli/php").provider("php").mark("error") { printf("Probe error\n"); printf(" errormsg %s\n", user_string($arg1)); printf(" request_file %s\n", user_string($arg2)); printf(" lineno %d\n", $arg3); } probe process("sapi/cli/php").provider("php").mark("exception__caught") { printf("Probe exception__caught\n"); printf(" classname %s\n", user_string($arg1)); } probe process("sapi/cli/php").provider("php").mark("exception__thrown") { printf("Probe exception__thrown\n"); printf(" classname %s\n", user_string($arg1)); } probe process("sapi/cli/php").provider("php").mark("execute__entry") { printf("Probe execute__entry\n"); printf(" request_file %s\n", user_string($arg1)); printf(" lineno %d\n", $arg2); } probe process("sapi/cli/php").provider("php").mark("execute__return") { printf("Probe execute__return\n"); printf(" request_file %s\n", user_string($arg1)); printf(" lineno %d\n", $arg2); } probe process("sapi/cli/php").provider("php").mark("function__entry") { printf("Probe function__entry\n"); printf(" function_name %s\n", user_string($arg1)); printf(" request_file %s\n", user_string($arg2)); printf(" lineno %d\n", $arg3); printf(" classname %s\n", user_string($arg4)); printf(" scope %s\n", user_string($arg5)); } probe process("sapi/cli/php").provider("php").mark("function__return") { printf("Probe function__return: %s\n", user_string($arg1)); printf(" function_name %s\n", user_string($arg1)); printf(" request_file %s\n", user_string($arg2)); printf(" lineno %d\n", $arg3); printf(" classname %s\n", user_string($arg4)); printf(" scope %s\n", user_string($arg5)); } probe process("sapi/cli/php").provider("php").mark("request__shutdown") { printf("Probe request__shutdown\n"); printf(" file %s\n", user_string($arg1)); printf(" request_uri %s\n", user_string($arg2)); printf(" request_method %s\n", user_string($arg3)); } probe process("sapi/cli/php").provider("php").mark("request__startup") { printf("Probe request__startup\n"); printf(" file %s\n", user_string($arg1)); printf(" request_uri %s\n", user_string($arg2)); printf(" request_method %s\n", user_string($arg3)); } 

用法:

 stap -c 'sapi/cli/php test.php' all_probes.stp 

请参阅:在PHP.net上使用带有PHP DTrace静态探针的SystemTap

根据问题,我喜欢error_reporting(E_ALL)混合回声测试(发现有问题的行/文件的错误发生在初始;你知道它并不总是行/文件php告诉你的权利?),IDE大括号匹配(解析“解析错误:语法错误,意外的$结束”问题)和print_r(); 出口; 转储(真正的程序员查看来源; p)。

你也不能用“memory_get_usage();”来打败phpdebug(检查sourceforge) 和“memory_get_peak_usage();” 找到问题的地方。

集成的调试器可以在您逐步浏览代码时观察变量值的变化。 但是,他们需要在服务器上安装软件,并在客户端上进行一定的配置。 这两者都需要定期维护以保持良好的工作状态。

print_r很容易编写,并保证可以在任何设置下工作。

通常我发现创建一个自定义日志功能,可以保存文件,存储调试信息,并最终重新打印在一个通用的页脚上。

您也可以覆盖常见的Exception类,以便这种类型的调试是半自动的。