你如何调试PHP脚本?

php eclipse debugging phpstorm xdebug

340264 观看

30回复

2969 作者的声誉

你如何调试PHP脚本?

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

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

作者: Marcel 的来源 发布者: 2008 年 8 月 3 日

回应 (30)


16

120250 作者的声誉

我已经使用Zend Studio(5.5)Zend Platform。这给了适当的调试,断点/踩到代码等,虽然付出了代价。

作者: Michael Stum 发布者: 03.08.2008 11:20

145

11615 作者的声誉

决定

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

作者: John Downey 发布者: 03.08.2008 11:28

2

87417 作者的声誉

print_r(debug_backtrace());

或类似的东西 :-)

作者: Orion Edwards 发布者: 03.08.2008 11:32

14

15934 作者的声誉

Derick Rethans的Xdebug非常好。我前段时间使用它,发现安装起来并不容易。完成后,如果没有它,你将无法理解你的管理方式:-)

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

作者: Christian Lescuyer 发布者: 04.08.2008 09:07

16

45023 作者的声誉

老实说,print和print_r()的组合打印出变量。我知道很多人更喜欢使用其他更高级的方法,但我发现这是最容易使用的方法。

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

作者: Teifion 发布者: 04.08.2008 09:28

0

16860 作者的声誉

为print_r()+1。用它来转储对象或变量的内容。为了使其更具可读性,请使用pre标签进行操作,这样您就不需要查看源代码。

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

var_dump($ thing) - 这对于查看子项的类型非常有用

作者: Polsonby 发布者: 05.08.2008 12:49

80

28920 作者的声誉

您可以使用Firephp作为firebug的附加组件来在与javascript相同的环境中调试php。

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

作者: Pat 发布者: 05.08.2008 05:22

0

911 作者的声誉

根据问题,我喜欢将error_reporting(E_ALL)与echo测试混合使用(找到错误的行/文件,错误发生在初始;你知道它并不总是行/文件php告诉你对吗?),IDE大括号匹配(解决“Parse error:syntax error,unexpected $ end”问题)和print_r(); 出口; 转储(真正的程序员查看源; p)。

你也不能用“memory_get_usage();”击败phpdebug(检查sourceforge)和“memory_get_peak_usage();” 找到问题领域。

作者: Eric Lamb 发布者: 06.08.2008 03:46

17

3385 作者的声誉

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

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

2)我使用Xdebug,但无法让GUI在我的Mac上正常工作。它至少打印出堆栈跟踪的可读版本。

作者: jlleblanc 发布者: 07.08.2008 12:25

1

0 作者的声誉

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

作者: Dan Grover 发布者: 15.08.2008 04:23

1

2395 作者的声誉

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

作者: Brendon-Van-Heyzen 发布者: 17.08.2008 06:38

8

11713 作者的声誉

对于使用print_r / echo来计算的太麻烦的问题,我使用我的IDE(PhpEd)调试功能。与我使用的其他IDE不同,PhpEd几乎不需要设置。我不使用它,因为我遇到任何问题,唯一的原因是,它是痛苦的缓慢。我不确定缓慢是特定于PhpEd还是任何php调试器。PhpEd不是免费的,但我相信它使用了一个开源调试器(如前面提到的XDebug)。再次,PhpEd的好处是它不需要我在过去发现真正相当繁琐的设置。

作者: Karim 发布者: 22.08.2008 03:33

4

30018 作者的声誉

对我来说,手动调试通常更快 - var_dump()并且debug_print_backtrace()是您操作逻辑所需的所有工具。

作者: Ross 发布者: 22.08.2008 03:36

26

5210 作者的声誉

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

快速浏览一下数据结构的使用方法var_dump()。不要使用,print_r()因为你必须用<pre>它包围它,它一次只打印一个var。

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

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

作者: Julio César 发布者: 22.08.2008 03:43

2

0 作者的声誉

Komodo IDE与xdebug配合得很好,即使是对于remore调试也是如此。它需要最少量的配置。您所需要的只是一个PHP版本,Komodo可以在本地使用它来逐步执行断点代码。如果您将脚本导入到komodo项目中,那么您可以通过鼠标单击设置断点,只需在eclipse中设置它以调试java程序。远程调试显然更难以使其正常工作(您可能必须使用工作区中的php脚本映射远程URL),而不是本地调试设置,如果您在MAC或Linux桌面上,这很容易配置。

作者: amit 发布者: 22.08.2008 03:44

0

27 作者的声誉

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

print_r易于编写,并保证可在任何设置中使用。

作者: Michael Luton 发布者: 22.08.2008 08:10

11

4906 作者的声誉

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

作者: Nacho 发布者: 26.08.2008 03:04

32

3735 作者的声誉

Xdebug和用于Notepad ++的DBGp插件用于重载bug,FirePHP用于轻量级的东西。快又脏?没有什么比dBug更好了

作者: djn 发布者: 15.09.2008 08:23

9

8876 作者的声誉

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

作者: Toby Allen 发布者: 17.09.2008 10:14

3

2046 作者的声誉

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

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

echo "<pre>".print_r($var, true)."</pre>";
作者: Nathan Strong 发布者: 18.09.2008 03:17

0

310 作者的声誉

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

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

作者: Joshi Spawnbrood 发布者: 22.10.2008 08:46

10

52143 作者的声誉

如果您不想搞砸输出,输出缓冲非常有用。我这样做是一个单行程,我可以随意评论/取消评论

 ob_start();var_dump(); user_error(ob_get_contents()); ob_get_clean();
作者: Ken 发布者: 22.10.2008 09:16

19

312 作者的声誉

PhpEd真的很棒。您可以进入/退出/退出功能。您可以运行特殊代码,检查变量,更改变量。真是太棒了。

作者: monk.e.boy 发布者: 05.02.2009 09:16

38

2933 作者的声誉

这是我的小调试环境:

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;
        }
    }
}
作者: eisberg 发布者: 29.06.2009 01:40

1

5903 作者的声誉

通过简单的var_dump一些关键变量可以轻松找到大多数错误,但这显然取决于您开发的应用程序类型。

对于更复杂的算法,步/断点/监视功能非常有用(如果没有必要)

作者: Petr Peller 发布者: 10.05.2010 09:18

3

1957 作者的声誉

当Rails无法使用时,我经常使用CakePHP。要调试错误,我通常会error.log在tmp文件夹中找到它并使用命令在终端中将其拖尾...

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

它让你从正在运行的蛋糕中运行对话框,这非常方便,如果你想在你可以使用的代码中输出一些东西。

$this->log('xxxx');

这通常可以让您了解发生了什么/错了什么。

作者: MintDeparture 发布者: 10.05.2010 09:29

11

11052 作者的声誉

我使用Netbeans和XDebug以及Easy XDebug FireFox附加组件

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

作者: Jannie Theunissen 发布者: 09.07.2010 03:14

2

5200 作者的声誉

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

作者: Mufaddal 发布者: 29.05.2012 12:43

2

21 作者的声誉

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

display_errors = Off
error_reporting = E_ALL 
display_errors = On

并且也使用了

error_log();
console_log();
作者: shekh danishuesn 发布者: 01.10.2015 11:16

1

77857 作者的声誉

PHP DBG

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

功能包括:

  • 逐步调试
  • 灵活断点(类方法,函数,文件:行,地址,操作码)
  • 使用内置eval轻松访问PHP()
  • 轻松访问当前执行代码
  • Userland API
  • SAPI不可知 - 易于集成
  • PHP配置文件支持
  • JIT Super Globals - 自己动手!!
  • 可选的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

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

DTrace的

如果您的系统支持DTrace动态跟踪(默认情况下在OS X上安装)并且您的PHP使用DTrace探针enabled(--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();"

要测试它,您可以通过以下方式访问任何docroot 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跟踪。

下面是示例script(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 Static Probes

作者: kenorb 发布者: 21.03.2016 12:34
32x32