PHP XDEBUG 扩展 | 文档

当 Xdebug 开启,无论 PHP 显示一个通知、警告或者错误,都将显示堆栈跟踪。堆栈跟踪的显示、显示的方式这些信息可以根据需要来配置。


在错误环境下(如果 disply_errors 在 php.ini 中设置),Xdebug 显示的错误堆栈跟踪在信息的数量上是相当保守的。这是因为大量的信息会让脚本的执行和把堆栈跟踪提供到浏览器上的速度减慢。然而用不同的设置让堆栈跟踪显示更多的细节信息是可以实现的。

堆栈跟踪中的变量

Xdebug 默认会显示目前在堆栈跟踪中产生的变量信息。在变量信息收集或者展示时都会占据相当一部分资源。然而在很多情况下变量信息的显示是很有用的,这也是为什么 Xdebug 有这个设置 xdebug.collect_params 。下方的脚本显示了这个设置的不同值会产生怎样的输出。

脚本

<?php
function foo$a ) {
    for (
$i 1$i $a['foo']; $i++) {
        if (
$i == 500000xdebug_break();
    }
}

set_time_limit(1);
$c = new stdClass;
$c->bar 100;
$a = array(
    
42 => false'foo' => 912124,
    
$c, new stdClassfopen'/etc/passwd''r' )
);
foo$a );
?>

结果

不同的这个设置 xdebug.collect_params 的值产生不同的输出,可以看下面:


( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 34
Call Stack
#TimeMemoryFunctionLocation
10.000158564{main}( )../stack.php:0
20.000462764foo( )../stack.php:47
ini_set('xdebug.collect_params', '1');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.000158132{main}( )../stack.php:0
20.000462380foo( array(5) )../stack.php:47
ini_set('xdebug.collect_params', '2');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.000158564{main}( )../stack.php:0
20.000462812foo( array(5) )../stack.php:47
ini_set('xdebug.collect_params', '3');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.000158564{main}( )../stack.php:0
20.000462812foo( array (42 => FALSE, 'foo' => 912124, 43 => class stdClass { public $bar = 100 }, 44 => class stdClass { }, 45 => resource(2) of type (stream)) )../stack.php:47
ini_set('xdebug.collect_params', '4');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.000158132{main}( )../stack.php:0
20.000462380foo( $a = array (42 => FALSE, 'foo' => 912124, 43 => class stdClass { public $bar = 100 }, 44 => class stdClass { }, 45 => resource(2) of type (stream)) )../stack.php:47

附加的信息

在上面显示的传递到每个函数的变量值,Xdebug 可以使用 xdebug.dump_globalsxdebug.dump.* 设置来选择性的显示选中的超级全局变量信息。这个 xdebug.dump_oncexdebug.dump_undefined 设置能轻微的修改在可获得的超级全局变量中何时显示以及显示哪个信息。用这个设置 xdebug.show_local_vars 可以通知 Xdebug 在顶层堆栈中显示所有可获得的变量,针对用户自定义的函数也是如此。示例展示在这里(使用的脚本来自上一个示例)。


( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 34
Call Stack
#TimeMemoryFunctionLocation
10.000158564{main}( )../stack.php:0
20.000462764foo( )../stack.php:47
ini_set('xdebug.collect_vars', 'on');
ini_set('xdebug.collect_params', '4');
ini_set('xdebug.dump_globals', 'on');
ini_set('xdebug.dump.SERVER', 'REQUEST_URI');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 33
Call Stack
#TimeMemoryFunctionLocation
10.000158132{main}( )../stack.php:0
20.000462436foo( )../stack.php:47
Dump $_SERVER
$_SERVER['REQUEST_URI'] =
string '/test/xdebug/docs/stack.php?level=5' (length=35)
ini_set('xdebug.collect_vars', 'on');
ini_set('xdebug.collect_params', '4');
ini_set('xdebug.dump_globals', 'on');
ini_set('xdebug.dump.SERVER', 'REQUEST_URI');
ini_set('xdebug.show_local_vars', 'on');

( ! ) Fatal error: Maximum execution time of 1 second exceeded in /home/httpd/html/test/xdebug/docs/stack.php on line 31
Call Stack
#TimeMemoryFunctionLocation
10.000158132{main}( )../stack.php:0
20.000562588foo( )../stack.php:47
Dump $_SERVER
$_SERVER['REQUEST_URI'] =
string '/test/xdebug/docs/stack.php?level=6' (length=35)

Variables in local scope (#2)
$a =
array
  42 => boolean false
  'foo' => int 912124
  43 => 
    object(stdClass)[1]
      public 'bar' => int 100
  44 => 
    object(stdClass)[2]
  45 => resource(2, stream)
$i =
int 275447

过滤

Xdebug 2.6 引入了堆栈跟踪的过滤功能。过滤器可以通过白名单包含、黑名单排除路径和类名前缀。你可以使用过滤器阻止第三方扩展包目录出现在堆栈跟踪中,或者其中只包含特定的命名空间的类。

设置过滤器只展示函数和方法,或者以 "Xdebug" 为前缀,你可以调用 xdebug_set_filter():

示例:
xdebug_set_filter(
	XDEBUG_FILTER_TRACING,
	XDEBUG_NAMESPACE_WHITELIST,
	[ '', 'Xdebug' ]
);

使用此过滤器设置,你将只看到以 "Xdebug" 开头的类调用的函数(没有类)和方法。这包括 PHP 内置的函数(比如 strlen())和调用 XdebugTest::bar()。过滤器不会强制 "Xdebug" 是命名空间名称,只有以完全限定类名开头才会进行严格的字符比较。在前缀中添加 \ 以确保只包含 Xdebug\ 名称空间中的类。

xdebug_set_filter() 的参数介绍的完整页面在其自己的文档页面。


相关设置


xdebug.cli_color
类型:整数,默认值: 0, 由 Xdebug > 2.2 引入

如果这个设置为 1,当在 CLI 模式并且输出是一个终端(tty)时,Xdebug 将会给 var_dumps 和堆栈跟踪输出附上颜色。在 Windows 系统下,需要安装 ANSICON 工具。

如果设置为 2,无论是否连上了终端和 ANSICON 是否安装,Xdebug 都将会给 var_dumps 和堆栈跟踪输出附上颜色。在这种情况下将不会看到转义的代码。

这篇文章了解更多信息。


xdebug.collect_includes
类型:布尔值,默认值: 1
这个设置默认为 1,控制 Xdebug 是否应该在 include(),include_once(),require() 或者 require_once() 的文件跟踪中写入文件名。

xdebug.collect_params
类型:整数,默认值: 0

这个设置默认为 0,当一个函数被函数跟踪或堆栈跟踪记录时,控制 Xdebug 是否收集参数传递给函数。

设置默认为 0 是因为非常大型的脚本会消耗巨大的内存,因此这样能让大型脚本运行起来。除了在大量函数调用和(或者)大型数据结构作为参数的脚本,都能最大程度的的安全的开启这个设置。 Xdebug 2 增加内存消耗时不会有这个问题,因为它从不将信息储存在内存中。相反它只会写入磁盘中。这意味着你需要查看磁盘空间使用情况。

这个设置有 4 个不同的值。针对每个值会有不同的信息显示。下面你将会看到每个值提供的信息是什么。也可以看堆栈跟踪特征的介绍提供的一些屏幕截图。

ValueArgument Information Shown
0None.
1Type and number of elements (f.e. string(6), array(8)).
2

Type and number of elements, with a tool tip for the full information 1.

3Full variable contents (with the limits respected as set by xdebug.var_display_max_children, xdebug.var_display_max_data and xdebug.var_display_max_depth.
4Full variable contents and variable name.
5PHP serialized variable contents, without the name. (New in Xdebug 2.3)

1 在 PHP 的 CLI 版本中将不会有 the tool tip,在输出文件中也没有。


xdebug.collect_vars
类型:布尔值,默认值: 0
这个设置告诉 Xdebug 在一个确定的作用域中收集哪些变量信息。这个分析就和 Xdebug 需要反向设计 PHP 的操作码数组一样慢。这个设置将不会记录不同变量拥有哪些值,这种情况使用 xdebug.collect_params 。这个设置只有在你希望使用 xdebug_get_declared_vars() 时开启。

xdebug.dump.*
类型:字符串,默认值: Empty

* 可以是 COOKIE,FILES,GET,POST,REQUEST,SERVER,SESSION 中的任何值。这 7 个设置控制了当错误状况出现时超级全局变量中的哪个数据将会显示。

每一个 php.ini 中的设置可以由逗号分隔的变量目录组成来实现转储,其中变量来自这个超级全局变量数组,或者是 * 他们所有。需要确保没有在这个设置中添加空格。

当错误出现为了转储 REMOTE_ADDR,REQUEST_METHOD 和所有 GET 参数,添加这些设置:

xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD
xdebug.dump.GET = *

xdebug.dump_globals
类型:布尔值,默认值: 1
当这个设置设置为 true 时,通过 xdebug.dump.* 配置的超级全局变量,Xdebug 会添加到屏幕堆栈和错误日志(如果开启了错误日志)。

xdebug.dump_once
类型:布尔值,默认值: 1
控制超级全局变量的值是在所有错误中(设置为 0)转储还是只在第一次错误中(设置为 1)转储。

xdebug.dump_undefined
类型:布尔值,默认值: 0
如果你想转储超级全局变量中未定义的值应该设置这个设置为 1,否则保留它设置为 0。

xdebug.file_link_format
类型:字符串,默认值: , 由 Xdebug > 2.1 引入

这个设置决定了在堆栈跟踪中显示文件名的链接形式。这允许 IDE 设置链接协议,通过点击 Xdebug 在堆栈跟踪中显示的文件名就能直接进入文件以及指定的行。格式会像这个示例:

myide://%f@%l

可能的格式说明符:

SpecifierMeaning
%fthe filename
%lthe line number

针对不同的 IDE 或者 OS,这里是一些让其工作的说明清单:

Firefox on Linux

  • 打开 about:config
  • 添加一个新的布尔值设置 "network.protocol-handler.expose.xdebug",设置为 "false"
  • 添加下面的代码到一个 shell 脚本 ~/bin/ff-xdebug.sh:
    #! /bin/sh
    
    f=`echo $1 | cut -d @ -f 1 | sed 's/xdebug:\/\///'`
    l=`echo $1 | cut -d @ -f 2`
    
    添加其中的一个(决定于是使用的 komodo,gvim 还是 netbeans):
    • komodo $f -l $l
    • gvim --remote-tab +$l $f
    • netbeans "$f:$l"
  • 让脚本执行 chmod +x ~/bin/ff-xdebug.sh
  • 设置 xdebug.file_link_formatxdebug://%f@%l

Windows and netbeans

  • 创建一个文件 netbeans.bat ,保存到你的路径(C:\windows 将会有效):
    @echo off
    setlocal enableextensions enabledelayedexpansion
    set NETBEANS=%1
    set FILE=%~2
    %NETBEANS% --nosplash --console suppress --open "%FILE:~19%"
    nircmd win activate process netbeans.exe
    

    注意:如果你不需要 nircmd 请移除最后一行。

  • 保存下面代码到 netbeans_protocol.reg:
    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\netbeans]
    "URL Protocol"=""
    @="URL:Netbeans Protocol"
    
    [HKEY_CLASSES_ROOT\netbeans\DefaultIcon]
    @="\"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe,1\""
    
    [HKEY_CLASSES_ROOT\netbeans\shell]
    
    [HKEY_CLASSES_ROOT\netbeans\shell\open]
    
    [HKEY_CLASSES_ROOT\netbeans\shell\open\command]
    @="\"C:\\Windows\\netbeans.bat\" \"C:\\Program Files\\NetBeans 7.1.1\\bin\\netbeans.exe\" \"%1\""
    

    注意:确保更换路径到 Netbeans(两次),如果你保存的地方不是 C:\windows 那么 netbeans.bat 批处理文件也是如此。

  • 双击 netbeans_protocol.reg 文件导入它到注册表。
  • 设置 xdebug.file_link_formatxdebug.file_link_format = "netbeans://open/?f=%f:%l"

xdebug.filename_format
Type: string, 默认值: ...%s%n, 由 Xdebug >= 2.6 引入

这个设置决定了在 HTML 堆栈跟踪中 Xdebug 呈现的文件名(默认: ...%s%n)和通过 xdebug_var_dump() 重载的位置信息(默认:%f)的格式。

此表列出了可能的格式说明符。示例输出是根据全路径 /var/www/vendor/mail/transport/mta.php 呈现。

说明符含义示例输出
%a祖辈:两个目录元素和文件名mail/transport/mta.php
%f全路径/var/www/vendor/mail/transport/mta.php
%n名称:只是文件名mta.php
%p父类:一个目录元素和文件名transport/mta.php
%s目录分隔符在 Linux,OSX 和其他类 Unix 系统上是 \,在 Windows 上是 /

xdebug.manual_url
类型 字符串,默认值:http://www.php.net, 由 Xdebug < 2.2.1 引入
这是函数跟踪和错误信息指向的手册页面链接的基准 URL。建议这个设置设为使用最近的镜像。

xdebug.show_error_trace
类型:整数,默认值: 0,由 Xdebug >= 2.4 引入
当这个设置设为 1,当错误发生时,即便这个错误已经被捕获,Xdebug 都将会显示堆栈跟踪。

xdebug.show_exception_trace
类型:整数,默认值:0
当这个设置设为 1,每当异常发生,即便这个异常已经捕获, Xdebug 都将会显示堆栈跟踪。

‘异常’错误在 PHP 7 中引入。


xdebug.show_local_vars
类型:整数,默认值:0
当这个设置设为其他不等于 0 的值时,错误状况下 Xdebug 生成的堆栈转储信息将会在顶层作用域显示所有的变量。注意这可能生成大量的信息,因此默认是关闭这个设置的。

xdebug.show_mem_delta
类型:整数,默认值:0
当这个设置设为其他不等于 0 的值时,Xdebug 会生成易于人类阅读的跟踪文件,将会向显示不同函数调用间内存使用的差异。如果 Xdebug 是配置为生成易于计算机阅读的跟踪文件则将会总是显示这个信息。

xdebug.var_display_max_children
类型:整数,默认值: 128

当变量通过 xdebug_var_dump()xdebug.show_local_vars 或者函数跟踪显示时,控制数组子元素和对象属性显示的数量。

设置值为 -1 ,可以取消显示的任何限制。

这个设置不会对通过远程调试功能发送到客户端的子元素数量有任何影响。


xdebug.var_display_max_data
类型:整数,默认值: 512

当变量通过 xdebug_var_dump()xdebug.show_local_vars 或者函数跟踪显示时,控制显示的字符串的最大长度。

设置值为 -1 ,可以取消显示的任何限制。

这个设置不会对通过远程调试功能发送到客户端的子元素数量有任何影响。


xdebug.var_display_max_depth
类型:整数,默认值: 3

当变量通过 xdebug_var_dump()xdebug.show_local_vars 或者函数跟踪显示时,控制数组子元素和对象属性嵌套多少层。

你可以选择的最大值是 1023 。你也可以使用 -1 作为值来选择这个最大的值。

这个设置不会对通过远程调试功能发送到客户端的子元素数量有任何影响。


相关函数


array xdebug_get_declared_vars()
返回声明的变量

返回一个数组,包含当前作用域中被声明的变量。这个设置需要 xdebug.collect_vars 来开启。

示例:

<?php
    
class strings {
        static function 
fix_strings($a$b) {
            foreach (
$b as $item) {
            }
            
var_dump(xdebug_get_declared_vars());
        }
    }
    
strings::fix_strings(array(1,2,3), array(4,5,6));
?>

返回:

array
  0 => string 'a' (length=1)
  1 => string 'b' (length=1)
  2 => string 'item' (length=4)

在 PHP 5.1 之前的版本中,变量名 "a" 不再返回到数组中,因为它不在函数 xdebug_get_declared_vars() 调用的作用域中。


array xdebug_get_function_stack()
返回堆栈的信息

返回一个类似于堆栈跟踪的数组。示例脚本:

示例:

<?php
    
class strings {
        function 
fix_string($a)
        {
            
var_dump(xdebug_get_function_stack());
        }

        function 
fix_strings($b) {
            foreach (
$b as $item) {
                
$this->fix_string($item);
            }
        }
    }

    
$s = new strings();
    
$ret $s->fix_strings(array('Derick'));
?>

返回:

array
  0 => 
    array
      'function' => string '{main}' (length=6)
      'file' => string '/var/www/xdebug_get_function_stack.php' (length=63)
      'line' => int 0
      'params' => 
        array
          empty
  1 => 
    array
      'function' => string 'fix_strings' (length=11)
      'class' => string 'strings' (length=7)
      'file' => string '/var/www/xdebug_get_function_stack.php' (length=63)
      'line' => int 18
      'params' => 
        array
          'b' => string 'array (0 => 'Derick')' (length=21)
  2 => 
    array
      'function' => string 'fix_string' (length=10)
      'class' => string 'strings' (length=7)
      'file' => string '/var/www/xdebug_get_function_stack.php' (length=63)
      'line' => int 12
      'params' => 
        array
          'a' => string ''Derick'' (length=8)


array xdebug_get_monitored_functions()
返回监控函数的信息
由 2.4 版本引入

返回一个数组结构,包含监控函数在脚本中哪里执行的信息。下面的示例展示了怎样使用它和返回的信息。

示例:

<?php
/* Start the function monitor for strrev and array_push: */
xdebug_start_function_monitor( [ 'strrev''array_push' ] );

/* Run some code: */
echo strrev("yes!"), "\n";

echo 
strrev("yes!"), "\n";

var_dump(xdebug_get_monitored_functions());
xdebug_stop_function_monitor();
?>  

返回:

/tmp/monitor-example.php:10:
array(2) {
  [0] =>
  array(3) {
    'function' =>
    string(6) "strrev"
    'filename' =>
    string(24) "/tmp/monitor-example.php"
    'lineno' =>
    int(6)
  }
  [1] =>
  array(3) {
    'function' =>
    string(6) "strrev"
    'filename' =>
    string(24) "/tmp/monitor-example.php"
    'lineno' =>
    int(8)
  }
}

integer xdebug_get_stack_depth()
返回当前堆栈的深度

返回堆栈的深度。脚本的主体 main{} 的深度为 0,每一个 inlcude 和 函数调用会让堆栈深度增加一级。


none xdebug_print_function_stack( [ string message [, int options ] ] )
显示当前函数的堆栈

以类似于 Xdebug 在错误状况下显示的方式来显示当前函数的堆栈。

"message" 参数允许用自己的头部信息来替换。(在 Xdebug 2.1 中引入

示例:

<?php
function foo$far$out )
{
    
xdebug_print_function_stack'Your own message' );
}
foo423141592654 );
?>

返回:

( ! ) Xdebug: Your own message in /home/httpd/html/test/xdebug/print_function_stack.php on line 5
Call Stack
#TimeMemoryFunctionLocation
10.0006653896{main}( )../print_function_stack.php:0
20.0007654616foo( 42, 3141592654 )../print_function_stack.php:7
30.0007654736xdebug_print_function_stack ( 'Your own message' )../print_function_stack.php:5

位掩码 "options" 允许你配置一些额外的选项。下面的选项是目前支持的:

XDEBUG_STACK_NO_DESC
如果这个选项设置,那么打印的堆栈跟踪将不会有头部。如果你想从错误句柄中打印一个堆栈跟踪,这将很有用。 打印的地方是xdebug_print_function_stack() 调用的地方。 由 Xdebug 2.3 引入


void xdebug_start_function_monitor( array $list_of_functions_to_monitor )
开启函数监控
由 2.4 版本引入

这个函数对函数参数语句中的函数条目开启了监控。函数监控允许找出作为参数的函数在代码中的哪里被调用了。这个可以用来跟踪在哪里使用了旧版本或不推荐的函数。

示例:

<?php
xdebug_start_function_monitor
( [ 'strrev''array_push' ] );
?>

你也可以添加类方法和静态方法到数组中来定义哪些函数被监控。例如,捕获静态调用 DramModel::canSee 和 动态调用 Whisky->drink,你需要这样开启监控:

示例:

<?php
xdebug_start_function_monitor
( [ 'DramModel::canSee''Whisky->drink'] );
?>

被定义的函数是大小写敏感的,一个静态方法的动态调用将不会被捕获。


void xdebug_stop_function_monitor()
停止监控函数
由 2.4 版本引入

这个函数停止函数监控。为了获得监控函数的清单,需要使用 xdebug_get_monitored_functions() 函数。