如何调试 PHP 脚本?

发布于 2024-07-05 09:50:25 字数 178 浏览 8 评论 0 原文

如何调试 PHP 脚本?

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

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

How do you debug PHP scripts?

I am aware of basic debugging such as using the Error Reporting. The breakpoint debugging in PHPEclipse is also quite useful.

What is the best (in terms of fast and easy) way to debug in phpStorm or any other IDE?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

奶气 2024-07-12 09:50:25

尝试 Eclipse PDT 设置一个具有您提到的调试功能的 Eclipse 环境。 与 var_dump 的旧方法相比,单步执行代码的能力是一种更好的调试方法,并在各个点进行打印以查看流程哪里出了问题。 当其他一切都失败时,我所拥有的只是 SSH 和 vim,我仍然用 var_dump()/die() 来查找代码出错的地方。

Try Eclipse PDT to setup an Eclipse environment that has debugging features like you mentioned. The ability to step into the code is a much better way to debug then the old method of var_dump and print at various points to see where your flow goes wrong. When all else fails though and all I have is SSH and vim I still var_dump()/die() to find where the code goes south.

时光倒影 2024-07-12 09:50:25

这是我的小调试环境:

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;
        }
    }
}

This is my little debug environment:

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;
        }
    }
}
可是我不能没有你 2024-07-12 09:50:25

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

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

You can use Firephp an add-on to firebug to debug php in the same environment as javascript.

I also use Xdebug mentioned earlier for profiling php.

千纸鹤带着心事 2024-07-12 09:50:25

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

我想说的是,直到我在 Uni 进行了一些微处理器编程之后,我才完全意识到这一点,而且甚至无法使用它。

In all honesty, a combination of print and print_r() to print out the variables. I know that many prefer to use other more advanced methods but I find this the easiest to use.

I will say that I didn't fully appreciate this until I did some Microprocessor programming at Uni and was not able to use even this.

明媚如初 2024-07-12 09:50:25

Derick Rethans 的 Xdebug 非常好。 前段时间用过,发现安装起来不太方便。 完成后,您将无法理解没有它如何管理:-)

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

Xdebug, by Derick Rethans, is very good. I used it some time ago and found it was not so easy to install. Once you're done, you won't understand how you managed without it :-)

There is a good article on Zend Developer Zone (installing on Linux doesn't seem any easier) and even a Firefox plugin, which I never used.

葬﹪忆之殇 2024-07-12 09:50:25

PhpEd 确实不错。 您可以单步进入/越过/退出函数。 您可以运行临时代码、检查变量、更改变量。 太神奇了。

PhpEd is really good. You can step into/over/out of functions. You can run ad-hoc code, inspect variables, change variables. It is amazing.

浅浅 2024-07-12 09:50:25

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

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

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

1) I use print_r(). In TextMate, I have a snippet for 'pre' which expands to this:

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

2) I use Xdebug, but haven't been able to get the GUI to work right on my Mac. It at least prints out a readable version of the stack trace.

神回复 2024-07-12 09:50:25

我使用了 Zend Studio (5.5) 以及 Zend 平台。 这提供了适当的调试、断点/单步执行代码等,尽管是有代价的。

I've used the Zend Studio (5.5), together with Zend Platform. That gives proper debugging, breakpoints/stepping over the code etc., although at a price.

日记撕了你也走了 2024-07-12 09:50:25

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

要快速查看数据结构,请使用 var_dump()。 不要使用 print_r(),因为您必须用

 包围它,并且它一次只打印一个 var。

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

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

XDebug is essential for development. I install it before any other extension. It gives you stack traces on any error and you can enable profiling easily.

For a quick look at a data structure use var_dump(). Don't use print_r() because you'll have to surround it with <pre> and it only prints one var at a time.

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

For a real debugging environment the best I've found is Komodo IDE but it costs $$.

兮子 2024-07-12 09:50:25

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

Xdebug and the DBGp plugin for Notepad++ for heavy duty bug hunting, FirePHP for lightweight stuff. Quick and dirty? Nothing beats dBug.

冷默言语 2024-07-12 09:50:25

如果您不想弄乱输出,那么输出缓冲非常有用。 我用一句话来做这件事,我可以随意评论/取消评论

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

Output buffering is very useful if you don't want to mess up your output. I do this in a one-liner which I can comment/uncomment at will

 ob_start();var_dump(); user_error(ob_get_contents()); ob_get_clean();
蓝戈者 2024-07-12 09:50:25

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

PhpEdit has a built in debugger, but I usually end up using echo(); and print_r(); the old fashioned way!!

写下不归期 2024-07-12 09:50:25

对于真正棘手的问题,使用 print_r/echo 来解决会太耗时,我使用 IDE 的 (PhpEd) 调试功能。 与我使用过的其他 IDE 不同,PhpEd 几乎不需要任何设置。 我不使用它来解决我遇到的任何问题的唯一原因是它的速度非常慢。 我不确定缓慢是特定于 PhpEd 或任何 php 调试器。 PhpEd 不是免费的,但我相信它无论如何都使用开源调试器之一(如前面提到的 XDebug)。 PhpEd 的好处是它不需要任何设置,我过去发现这非常繁琐。

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.

回忆凄美了谁 2024-07-12 09:50:25

对我来说,手动调试通常更快 - var_dump()debug_print_backtrace() 都是您武装逻辑所需的工具。

Manual debugging is generally quicker for me - var_dump() and debug_print_backtrace() are all the tools you need to arm your logic with.

樱花坊 2024-07-12 09:50:25

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

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

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

Well, to some degree it depends on where things are going south. That's the first thing I try to isolate, and then I'll use echo/print_r() as necessary.

NB: You guys know that you can pass true as a second argument to print_r() and it'll return the output instead of printing it? E.g.:

echo "<pre>".print_r($var, true)."</pre>";
猫性小仙女 2024-07-12 09:50:25

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

I use Netbeans with XDebug.
Check it out at its website for docs on how to configure it.
http://php.netbeans.org/

萌梦深 2024-07-12 09:50:25

我将 Netbeans 与 XDebug 和 Easy XDebug FireFox Add-on

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

I use Netbeans with XDebug and the Easy XDebug FireFox Add-on

The add-on is essential when you debug MVC projects, because the normal way XDebug runs in Netbeans is to register the dbug session via the url. With the add-on installed in FireFox, you would set your Netbeans project properties -> Run Configuratuion -> Advanced and select "Do Not Open Web Browser" You can now set your break points and start the debugging session with Ctrl-F5 as usual. Open FireFox and right-click the Add-on icon in the right bottom corner to start monitoring for breakpoints. When the code reaches the breakpoint it will stop and you can inspect your variable states and call-stack.

孤君无依 2024-07-12 09:50:25

print_r(debug_backtrace());

或类似的东西 :-)

print_r( debug_backtrace() );

or something like that :-)

掩于岁月 2024-07-12 09:50:25

Komodo IDE 与 xdebug 配合良好,甚至可以进行更多调试。 它需要最少的配置。 您所需要的只是 Komodo 可以在本地使用的 php 版本,以便在断点上单步执行代码。 如果您将脚本导入到komodo项目中,那么您可以通过单击鼠标来设置断点,就像在eclipse中设置断点以调试java程序一样。
要使其正常工作,远程调试显然比本地调试设置更棘手(您可能必须使用工作区中的 php 脚本映射远程 url),如果您使用的是 MAC 或 Linux 桌面,本地调试设置则非常容易配置。 。

Komodo IDE works well with xdebug, even for the remore debugging. It needs minimum amount of configuration. All you need is a version of php that Komodo can use locally to step through the code on a breakpoint. If you have the script imported into komodo project, then you can set breakpoints with a mouse-click just how you would set it inside eclipse for debugging a java program.
Remote debugging is obviously more tricky to get it to work correctly ( you might have to map the remote url with a php script in your workspace ) than a local debugging setup which is pretty easy to configure if you are on a MAC or a linux desktop.

始于初秋 2024-07-12 09:50:25

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

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

它为您提供了正在发生的事情的运行对话框,这非常方便,如果你想在代码中输出一些东西,你可以使用。

$this->log('xxxx');

这通常可以让您很好地了解发生了什么/出了什么问题。

I often use CakePHP when Rails isn't possible. To debug errors I usually find the error.log in the tmp folder and tail it in the terminal with the command...

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

It give's you running dialog from cake of what is going on, which is pretty handy, if you want to output something to it mid code you can use.

$this->log('xxxx');

This can usually give you a good idea of what is going on/wrong.

全部不再 2024-07-12 09:50:25

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

Nusphere is also a good debugger for php
nusphere

枉心 2024-07-12 09:50:25

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

display_errors = Off
error_reporting = E_ALL 
display_errors = On

并且还使用了

error_log();
console_log();

There are many PHP debugging techniques that can save you countless hours when coding. An effective but basic debugging technique is to simply turn on error reporting. Another slightly more advanced technique involves using print statements, which can help pinpoint more elusive bugs by displaying what is actually going onto the screen. PHPeclipse is an Eclipse plug-in that can highlight common syntax errors and can be used in conjunction with a debugger to set breakpoints.

display_errors = Off
error_reporting = E_ALL 
display_errors = On

and also used

error_log();
console_log();
半步萧音过轻尘 2024-07-12 09:50:25

PHP DBG

作为 SAPI 模块实现的交互式单步调试 PHP 调试器,可以让您完全控制环境而不影响代码的功能或性能。 它旨在成为 PHP 5.4+ 的轻量级、功能强大、易于使用的调试平台,并且随 PHP 5.6 一起提供。

功能包括:

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

参见截图:

PHP DBG - 单步调试 - 屏幕截图

PHP DBG - 单步调试 - 屏幕截图

主页:http://phpdbg.com/

PHP Error - 更好的 PHP 错误报告

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

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

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

然后所有错误都会为您提供诸如回溯、代码上下文、函数参数、服务器变量等信息。例如:

< a href="https://i.sstatic.net/csob7.png" rel="nofollow noreferrer">PHP 错误 |改进 PHP 的错误报告 - 回溯的屏幕截图
PHP 错误| 改进 PHP 的错误报告 - 回溯的屏幕截图
PHP 错误| 改进 PHP 错误报告 - backtrace 的屏幕截图

功能包括:

  • 使用起来很简单,对于正常请求和 ajaxy 请求,它只是
  • 在浏览器中显示一个文件错误
  • AJAX 请求暂停,允许您自动重新运行它们
  • 使错误尽可能严格(鼓励代码质量,并倾向于提高性能)
  • 整个堆栈跟踪中的代码片段
  • 提供更多信息(例如完整的函数签名)
  • 修复一些错误消息,这些错误消息只是简单的错误
  • 语法突出显示
  • 看起来很漂亮!
  • 自定义手动
  • 打开和关闭它
  • 运行特定部分而不报告错误
  • 忽略文件允许您避免突出显示堆栈跟踪
  • 应用程序文件中的代码; 当发生错误时,这些会被优先考虑!

主页:http://phperror.net/

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

我的分支(带有额外的修复):https://github.com/JosephLenton/PHP-Error com/kenorb-contrib/PHP-Error" rel="nofollow noreferrer">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< /code>):

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));
}

主页:dtruss-lamp at GitHub

这是简单的用法:

  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 和 DTrace,位于 php.net


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 静态探针结合使用

PHP DBG

The Interactive Stepthrough PHP Debugger implemented as a SAPI module which can give give you complete control over the environment without impacting the functionality or performance of your code. It aims to be a lightweight, powerful, easy to use debugging platform for PHP 5.4+ and it's shipped out-of-box with PHP 5.6.

Features includes:

  • Stepthrough Debugging
  • Flexible Breakpoints (Class Method, Function, File:Line, Address, Opcode)
  • Easy Access to PHP with built-in eval()
  • Easy Access to Currently Executing Code
  • Userland API
  • SAPI Agnostic - Easily Integrated
  • PHP Configuration File Support
  • JIT Super Globals - Set Your Own!!
  • Optional readline Support - Comfortable Terminal Operation
  • Remote Debugging Support - Bundled Java GUI
  • Easy Operation

See the screenshots:

PHP DBG - Stepthrough Debugging - screenshot

PHP DBG - Stepthrough Debugging - screenshot

Home page: http://phpdbg.com/

PHP Error - Better error reporting for PHP

This is very easy to use library (actually a file) to debug your PHP scripts.

The only thing that you need to do is to include one file as below (at the beginning on your code):

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

Then all errors will give you info such as backtrace, code context, function arguments, server variables, etc. For example:

PHP Error | Improve Error Reporting for PHP - screenshot of backtrace
PHP Error | Improve Error Reporting for PHP - screenshot of backtrace
PHP Error | Improve Error Reporting for PHP - screenshot of backtrace

Features include:

  • 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!

Home page: http://phperror.net/

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

My fork (with extra fixes): https://github.com/kenorb-contrib/PHP-Error

DTrace

If your system supports DTrace dynamic tracing (installed by default on OS X) and your PHP is compiled with the DTrace probes enabled (--enable-dtrace) which should be by default, this command can help you to debug PHP script with no time:

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); }'

So given the following alias has been added into your rc files (e.g. ~/.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); }"'

you may trace your script with easy to remember alias: trace-php.

Here is more advanced dtrace script, just save it into dtruss-php.d, make it executable (chmod +x dtruss-php.d) and run:

#!/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));
}

Home page: dtruss-lamp at GitHub

Here is simple usage:

  1. Run: sudo dtruss-php.d.
  2. On another terminal run: php -r "phpinfo();".

To test that, you can go to any docroot with index.php and run PHP builtin server by:

php -S localhost:8080

After that you can access the site at http://localhost:8080/ (or choose whatever port is convenient for you). From there access some pages to see the trace output.

Note: Dtrace is available on OS X by default, on Linux you probably need dtrace4linux or check for some other alternatives.

See: Using PHP and DTrace at php.net


SystemTap

Alternatively check for SystemTap tracing by installing SystemTap SDT development package (e.g. yum install systemtap-sdt-devel).

Here is example script (all_probes.stp) for tracing all core PHP static probe points throughout the duration of a running PHP script with SystemTap:

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));
}

Usage:

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

See: Using SystemTap with PHP DTrace Static Probes at php.net

一梦浮鱼 2024-07-12 09:50:25

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

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

The most of bugs can be found easily by simply var_dumping some of key variables, but it obviously depends on what kind of application you develop.

For a more complex algorithms the step/breakpoint/watch functions are very helpful (if not necessary)

躲猫猫 2024-07-12 09:50:25

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

i use zend studio for eclipse with the built in debugger. Its still slow compared to debugging with eclipse pdt with xdebug. Hopefully they will fix those issues, the speed has improved over the recent releases but still stepping over things takes 2-3 seconds.
The zend firefox toolbar really makes things easy (debug next page, current page, etc). Also it provides a profiler that will benchmark your code and provide pie-charts, execution time, etc.

初见终念 2024-07-12 09:50:25

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

In a production environment, I log relevant data to the server's error log with error_log().

心头的小情儿 2024-07-12 09:50:25

根据问题,我喜欢将 error_reporting(E_ALL) 与 echo 测试混合(以查找最初发生错误的有问题的行/文件;你知道它并不总是 php 告诉你的行/文件吗?),IDE 大括号匹配(解决“解析错误:语法错误,意外的 $end”问题)和 print_r(); 出口; 转储(真正的程序员查看源代码;p)。

你也无法用“memory_get_usage();”击败phpdebug(检查sourceforge)。 和“memory_get_peak_usage();” 找到问题区域。

Depending on the issue I like a combination of error_reporting(E_ALL) mixed with echo tests (to find the offending line/file the error happened in initally; you KNOW it's not always the line/file php tells you right?), IDE brace matching (to resolve "Parse error: syntax error, unexpected $end" issues), and print_r(); exit; dumps (real programmers view the source ;p).

You also can't beat phpdebug (check sourceforge) with "memory_get_usage();" and "memory_get_peak_usage();" to find the problem areas.

我的黑色迷你裙 2024-07-12 09:50:25

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

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

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

+1 for print_r(). Use it to dump out the contents of an object or variable. To make it more readable, do it with a pre tag so you don't need to view source.

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

Also var_dump($thing) - this is very useful to see the type of subthings

等风也等你 2024-07-12 09:50:25

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

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

The integrated debuggers where you can watch the values of variable change as you step through code are really cool. They do, however, require software setup on the server and a certain amount of configuration on the client. Both of which require periodic maintenance to keep in good working order.

A print_r is easy to write and is guaranteed to work in any setup.

沫尐诺 2024-07-12 09:50:25

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

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

Usually I find create a custom log function able to save on file, store debug info, and eventually re-print on a common footer.

You can also override common Exception class, so that this type of debugging is semi-automated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文