如何调试PHP脚本?

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

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


当前回答

在某种程度上,这取决于事情的走向。这是我尝试分离的第一件事,然后在必要时使用echo/print_r()。

注:你们知道你可以把true作为第二个参数传递给print_r(),它会返回输出而不是打印它吗?例如:

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

其他回答

手动调试对我来说通常更快——var_dump()和debug_print_backtrace()是你需要用来武装你的逻辑的所有工具。

尝试Eclipse PDT来设置具有您提到的调试特性的Eclipse环境。与var_dump的老方法相比,进入代码的能力是一种更好的调试方法,并在各个点打印,以查看流在哪里出错。当所有这些都失败了,虽然,我只有SSH和vim,我仍然var_dump()/die()找到哪里的代码出错。

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

For the really gritty problems that would be too time consuming to use print_r/echo to figure out I use my IDE's (PhpEd) debugging feature. Unlike other IDEs I've used, PhpEd requires pretty much no setup. the only reason I don't use it for any problems I encounter is that it's painfully slow. I'm not sure that slowness is specific to PhpEd or any php debugger. PhpEd is not free but I believe it uses one of the open-source debuggers (like XDebug previously mentioned) anyway. The benefit with PhpEd, again, is that it requires no setup which I have found really pretty tedious in the past.

PHP DBG

交互式逐步PHP调试器实现为一个SAPI模块,它可以让你完全控制环境,而不影响代码的功能或性能。它的目标是成为一个轻量级、功能强大、易于使用的PHP 5.4+调试平台,它随PHP 5.6一起发布。

功能包括:

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

请看截图:

首页:http://phpdbg.com/

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

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

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

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

然后所有的错误都会给你一些信息,比如回溯、代码上下文、函数参数、服务器变量等等。例如:

功能包括:

trivial to use, it's just one file errors displayed in the browser for normal and ajaxy requests AJAX requests are paused, allowing you to automatically re-run them makes errors as strict as possible (encourages code quality, and tends to improve performance) code snippets across the whole stack trace provides more information (such as full function signatures) fixes some error messages which are just plain wrong syntax highlighting looks pretty! customization manually turn it on and off run specific sections without error reporting ignore files allowing you to avoid highlighting code in your stack trace application files; these are prioritized when an error strikes!

首页: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

下面是简单的用法:

执行命令sudo dtruss-php.d。 在另一个终端运行:php -r "phpinfo();"。

为了测试这一点,你可以使用index.php找到任何docroot,并通过以下方式运行PHP内置服务器:

php -S localhost:8080

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

注意:Dtrace默认在OS X上可用,在Linux上你可能需要dtrace4linux或检查一些其他替代方案。

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


SystemTap

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

下面是一个示例脚本(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上使用SystemTap和PHP DTrace静态探针