PHP XDEBUG 扩展 | 文档

这个章节描述了 Xdebug 中可用的所有函数。


相关函数


void var_dump( [mixed var [, ...]] )
显示变量的细节方面的信息

这个函数由 Xdebug 重载,看 xdebug_var_dump() 的描述。


bool xdebug_break()
发送一个断点到调试客户端

这个函数能让调试器在特定的行中断,就像一个普通文件/行断点被设置在该行一样。


string xdebug_call_class( [int $depth = 2] )
返回调用的类,如果堆栈帧不存在返回 NULL,如果堆栈帧没有类信息则返回 FALSE

这个函数返回定义当前方法的类的名称,如果没有与此调用关联的类则返回 FALSE

示例:

<?php
class Strings
{
    static function 
fix_string($a)
    {
        echo
            
xdebug_call_class().
            
"::".
            
xdebug_call_function().
            
" is called at ".
            
xdebug_call_file().
            
":".
            
xdebug_call_line();
    }
}

$ret Strings::fix_string'Derick' );
?>

返回:

Called @ /home/httpd/html/test/xdebug_caller.php:17 from ::{main}

为了从更早的堆栈帧中获得信息,请使用可选的 $depth 参数。值为 1 则返回执行 xdebug_call_class() 的方法的调用信息:

示例:

<?php
class Strings
{
    static function 
fix_string$a )
    {
        echo
            
xdebug_call_class).
            
"::".
            
xdebug_call_function).
            
" is called at ".
            
xdebug_call_file).
            
":".
            
xdebug_call_line);
    }
}

$ret Strings::fix_string'Derick' );
?>

返回:

Strings::fix_string is called at /home/httpd/html/test/xdebug_caller:17

值为 2 (默认)则返回当前方法的“祖父母”的调用信息:

示例:

<?php
class Strings
{
    static function 
fix_string$a )
    {
        echo
            
xdebug_call_class).
            
"::".
            
xdebug_call_function).
            
" is called at ".
            
xdebug_call_file).
            
":".
            
xdebug_call_line);
    }

    static function 
fix_strings( array $a )
    {
        foreach ( 
$a as $element )
        {
            
self::fix_string$a );
        }
    }
}

$ret Strings::fix_strings( [ 'Derick' ] );
?>

返回:

Strings::fix_strings is called at /home/httpd/html/test/xdebug_caller:25

值为 0 则返回调用对应 xdebug_call_* 方法的调用信息:

示例:

<?php
class Strings
{
    static function 
fix_string$a )
    {
        echo
            
xdebug_call_class).
            
"::".
            
xdebug_call_function).
            
" is called at ".
            
xdebug_call_file).
            
":".
            
xdebug_call_line);
    }

    static function 
fix_strings( array $a )
    {
        foreach ( 
$a as $element )
        {
            
self::fix_string$a );
        }
    }
}

$ret Strings::fix_strings( [ 'Derick' ] );
?>

返回:

::xdebug_call_function is called at /home/httpd/html/test/xdebug_caller:13

string xdebug_call_file( [int $depth = 2] )
返回调用文件,如果堆栈帧不存在则返回 NULL

这个函数返回执行当前函数或者方法的文件名。

为了获得更早的堆栈帧的信息,请使用可选的 $depth 参数。

有关示例和更多的信息,查看 xdebug_call_class()


string xdebug_call_function( [int $depth = 2] )
返回调用的函数或者方法,如果堆栈帧不存在则返回 NULL,如果堆栈帧没有函数或者方法信息则返回 FALSE

这个函数返回当前函数或者方法的名称。

为了从更早的堆栈帧中获得信息,请使用可选的 $depth 参数。

有关示例和更多的信息,查看 xdebug_call_class()


int xdebug_call_line( [int $depth = 2] )
返回调用的行号,如果堆栈帧不存在则返回 NULL

这个函数返回当前函数或者方法被调用的行号。

为了从更早的堆栈帧中获得信息,请使用可选的 $depth 参数。

有关示例和更多的信息,查看 xdebug_call_class()


boolean xdebug_code_coverage_started()
返回代码覆盖是否活跃

返回代码覆盖是否已经开启。

示例:

<?php
    var_dump
(xdebug_code_coverage_started());

    
xdebug_start_code_coverage();

    
var_dump(xdebug_code_coverage_started());
?>  

返回:

bool(false)
bool(true)


void xdebug_debug_zval( [string varname [, ...]] )
显示一个变量的信息

这个函数显示一个或更多变量的结构化的信息,包含它的类型、值和引用信息。数组是递归性地探测值的。为了绕过变量本身实际上已经传递给了函数这个问题,这个函数的实现不同于 PHP 的 debug_zval_dump() 函数的实现。Xdebug的版本更好是因为它使用这个变量名在内部符号表中查找这个变量,而且能直接访问所有的属性而不用实际地传递一个变量到函数来处理。结果是这个函数返回的信息比 PHP 自己的函数显示的容器信息更加准确。

任何变量的支持是自 Xdebug 2.3 开始的,除了简单的变量名(比如下方的 "a[2]")。

示例:

<?php
    $a 
= array(123);
    
$b =& $a;
    
$c =& $a[2];

    
xdebug_debug_zval('a');
    
xdebug_debug_zval("a[2]");
?>

返回:

a: (refcount=2, is_ref=1)=array (
	0 => (refcount=1, is_ref=0)=1, 
	1 => (refcount=1, is_ref=0)=2, 
	2 => (refcount=2, is_ref=1)=3)
a[2]: (refcount=2, is_ref=1)=3

void xdebug_debug_zval_stdout( [string varname [, ...]] )
返回一个变量标准输出的信息

这个函数显示一个或更多变量的结构化的信息,包含它的类型、值和引用信息。数组是递归性地探测值的。和 xdebug_debug_zval 不同的是这个信息不是通过网络服务器 API 层显示的,而是直接输出显示(所以当你用 Apache 单进程模式运行它,它在控制台结束)。

示例:

<?php
    $a 
= array(123);
    
$b =& $a;
    
$c =& $a[2];

    
xdebug_debug_zval_stdout('a');

返回:

a: (refcount=2, is_ref=1)=array (
	0 => (refcount=1, is_ref=0)=1, 
	1 => (refcount=1, is_ref=0)=2, 
	2 => (refcount=2, is_ref=1)=3)

void xdebug_disable()
禁止堆栈跟踪

错误状态时禁止显示堆栈跟踪。


void xdebug_dump_superglobals()
显示超级全局变量的信息

这个函数以 xdebug.dump.* 在 php.ini 中指定的设置转储超级全局变量元素的值。例如下面在 php.ini 中的设置:

示例:

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

查询字符串:
?var=fourty%20two&array[a]=a&array[9]=b

返回:

Dump $_SERVER
$_SERVER['REMOTE_ADDR'] =
string '127.0.0.1' (length=9)
Dump $_GET
$_GET['var'] =
string 'fourty two' (length=10)
$_GET['array'] =
array
  'a' => string 'a' (length=1)
  9 => string 'b' (length=1)

void xdebug_enable()
开启堆栈跟踪

错误状态时开启显示堆栈跟踪。


array xdebug_get_code_coverage()
返回代码覆盖信息

返回一个数组结构,包含哪些行在脚本中(包括 inlcude 的文件)被执行了的信息。下面的示例展示了一个指定文件的代码覆盖:

示例:

<?php
    xdebug_start_code_coverage
();

    function 
a($a) {
        echo 
$a 2.5;
    }

    function 
b($count) {
        for (
$i 0$i $count$i++) {
            
a($i 0.17);
        }
    }

    
b(6);
    
b(10);

    
var_dump(xdebug_get_code_coverage());
?>  

返回:

array
  '/home/httpd/html/test/xdebug/docs/xdebug_get_code_coverage.php' => 
    array
      5 => int 1
      6 => int 1
      7 => int 1
      9 => int 1
      10 => int 1
      11 => int 1
      12 => int 1
      13 => int 1
      15 => int 1
      16 => int 1
      18 => int 1

string xdebug_get_collected_errors( [int clean] )
返回收集的所有错误信息
在 2.1 版本引入

这个函数从缓存集合区返回所有的错误,缓存区包含当用 xdebug_start_error_collection() 把错误集合开启时存储在这里的所有错误信息。

默认设置这个函数不会清除错误缓存集合区。如果传递 "true" 作为这个函数的参数,那么缓存区也将会被清除。

这个函数会返回一个字符串,包含用 "Xdebug 表格"格式化的所有收集的错误。


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_headers()
通过调用 PHP header() 函数,返回设置的所有头部信息
在 2.1 版本引入

以数组的形式返回由 PHP header() 函数设置或者由 PHP 内部设置的(比如通过 setcookie())所有的头部。

示例:

<?php
header
"X-Test""Testing" );
setcookie"TestCookie""test-value" );
var_dumpxdebug_get_headers() );
?>

返回:

array(2) {
  [0]=>
  string(6) "X-Test"
  [1]=>
  string(33) "Set-Cookie: TestCookie=test-value"
}

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

string xdebug_get_profiler_filename()
返回 profile 信息的文件名

返回用来保存 profile 信息的文件的名字。


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

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


string xdebug_get_tracefile_name()
返回函数跟踪的文件名

返回用来跟踪脚本输出的文件名。当 xdebug.auto_trace 开启时这个设置很有用。


bool xdebug_is_debugger_active()
返回调试会话是否活跃
由 2.6 版本引入

如果通过 DBGPS 的调试会话,与客户端连接当前处于活跃状态,则返回 true,否则,返回 false


bool xdebug_is_enabled()
返回堆栈跟踪是否开启

在发生错误的情况下,返回堆栈跟踪是否会显示。


int xdebug_memory_usage()
返回当前的内存使用

返回当前脚本使用的内存数量。在 PHP 5.2.1 之前,只工作在 PHP 使用 --enable-memory-limit 编译之后。在 PHP 5.2.1 和之后的版本中这个函数总是有效的。


int xdebug_peak_memory_usage()
返回内存使用的峰值

返回截止到目前脚本使用内存的最大数量。在 PHP 5.2.1 之前,只工作在 PHP 使用 --enable-memory-limit 编译之后。在 PHP 5.2.1 和之后的版本中这个函数总是有效的。


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_set_filter( int $group, int $list_type, array $configuration )
设置过滤器
由 2.6 版本引入

当展示堆栈跟踪或者记录函数跟踪时,或者当收集代码覆盖时,这个函数配置 Xdebug 使用的过滤器。过滤器配置应用于每个独立的执行单元(函数,方法,脚本主体)。

第一个参数, $group 选择要设置过滤器的功能。目前有两组

XDEBUG_FILTER_TRACING
用于在错误之上过滤堆栈跟踪以及函数跟踪的过滤器组。
XDEBUG_FILTER_CODE_COVERAGE
用于限制 Xdebug 代码覆盖分析的文件路径的过滤器组。
每个组都可以单独配置。

你可以设置不同类型的过滤器。对于文件路径或完全限定类名,有一个白名单和黑名单选项。 XDEBUG_FILTER_CODE_COVERAGE 组仅支持 XDEBUG_PATH_WHITELISTXDEBUG_PATH_BLACKLIST,和 XDEBUG_FILTER_NONE。所有的匹配都不区分大小写。

用做第二个参数 "$list_type" 的常量是:

XDEBUG_PATH_WHITELIST

设置文件路径的白名单。如果执行单元的文件路径以作为第三个参数 $configuration 的数组中的任何前缀作为前缀,则输出中包含执行单元。

请注意,前缀 "/home/derick" 也会匹配 "/home/derickrethans" 中的文件,因此建议在前缀中添加尾部斜杠以防止这种情况发生。

XDEBUG_PATH_BLACKLIST
设置文件路径的黑名单。如果执行单元的文件路径以 $configuration 数组中的任何前缀作为前缀,则它将从输出中排除。
XDEBUG_NAMESPACE_WHITELIST

为类前缀设置白名单。如果命名空间扩展后的类名,匹配 $configuration 数组中的前缀中的其中一个,则输出中包含执行单元。 "" 是特殊的,表示不属于类的函数。这些是用户定义或内置的 PHP 函数(例如 strlen())。

命名空间扩展在 PHP 中自动识别,它的引擎会始终看见完全限定类名。在下面的代码中,完全限定类名 DramIO\Whisky

Example:

<?php
namespace DramIO;

class 
Whisky {
}

为了匹配命名空间中所有类,建议使用命名空间分隔符指定前缀。

XDEBUG_NAMESPACE_BLACKLIST
与白名单相反。仅当前缀匹配了 $configuration 数组中前缀的其中一个,则执行的单元被排除。
XDEBUG_FILTER_NONE
关闭所选 $group 的过滤器。

不能同时配置黑名单和白名单,或者为路径和命名空间配置黑名单/白名单。 在任意的一个时间,四种列出的类型中只有一种能活跃。但是可以使用 XDEBUG_FILTER_NONE 完全关闭过滤器。

排除跟踪 vendor 子目录中所有文件:

示例:

<?php
xdebug_set_filter
XDEBUG_FILTER_TRACINGXDEBUG_PATH_BLACKLIST, [ __DIR__ "/vendor/" ] );
?>

包含跟踪中的函数调用(不在类名之下),ezcDramIO\ 类下的方法调用:

示例:

<?php
xdebug_set_filter
XDEBUG_FILTER_TRACINGXDEBUG_NAMESPACE_WHITELIST, [ """ezc""DramIO\" ] );
?>

只在 src 子目录下执行代码覆盖分析:

示例:

<?php
xdebug_set_filter
XDEBUG_FILTER_CODE_COVERAGEXDEBUG_PATH_WHITELIST, [ __DIR__ "/src/" ] );
?>

void xdebug_start_code_coverage( [int options] )
开启代码覆盖e

这个函数开始统计代码覆盖的信息。这个信息由二维数组组成,数组主下标是执行的文件名字,第二个索引是行号。返回的值代表代码行是否已经执行或者是不可执行的代码行。

每一行返回的值:

  • 1: 该行已经执行
  • -1: 该行没有执行
  • -2: 该行没有可执行代码
-1 只有在 XDEBUG_CC_UNUSED 开启时会返回,值 -2 只有在 XDEBUG_CC_UNUSEDXDEBUG_CC_DEAD_CODE 都开启时才会返回。

这个函数有两个选项,他们是位字段:

XDEBUG_CC_UNUSED
开启代码扫描来找出哪一行被执行过了。没有这个选项返回的数组中只有已经被执行过的代码行。
XDEBUG_CC_DEAD_CODE
开启分支分析来计算代码是否被执行过了。
XDEBUG_CC_BRANCH_CHECK
开启执行路径分析。
开启这些选项会让代码覆盖的速度大幅度的降低。

可以像下面示例中展示的一样使用这个选项。

示例:

<?php
xdebug_start_code_coverage
XDEBUG_CC_UNUSED XDEBUG_CC_DEAD_CODE );
?>

void xdebug_start_error_collection()
开启记录所有的通知、警告和错误,并且阻止他们的显示
在 2.1 版本引入

当这个函数执行时, Xdebug 将会让 PHP 不显示任何通知、警告和错误。而是根据 Xdebug 正常标准的错误格式化规则来格式化这些信息并储存在缓存区中。直到调用 xdebug_stop_error_collection() 才会停止。

这个缓存区的内容可以通过调用 xdebug_get_collected_errors 来获取并接着显示出来。如果你想阻止 Xdebug 强力的错误报告功能破坏你的布局,这个函数非常有用。


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'] );
?>

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


string xdebug_start_trace( [ string trace_file [, integer options] ] )
开启一个新的函数跟踪

开启从该函数到 trace_file 参数的文件的跟踪。如果没有函数名指定,那么跟踪文件将会被配置 xdebug.trace_output_dir 设置中的目录替代。

如果文件名作为第一个参数给出,则名字是针对当前工作目录的相对路径。这个当前工作目录可能不同于你所期望的,所以如果要指定一个文件名请使用一个绝对路径。可以使用 PHP 的 getcwd() 函数来计算出当前工作目录是什么。

跟踪文件的名字是 "{trace_file}.xt"。如果 xdebug.auto_trace 开启,那么 "{trace_file}.xt" 在 "{trace_file}" 部分的格式会取决于 xdebug.trace_outpuut_name 的设置。这个 options 是一个位字段,目前有这几种选项:

XDEBUG_TRACE_APPEND (1)
让跟踪文件打开是追加模式而不是覆盖模式 overwrite mode
XDEBUG_TRACE_COMPUTERIZED (2)
创建一个跟踪文件,以 "xdebug.trace_format" 中值为 1 的格式
XDEBUG_TRACE_HTML (4)
创建一个 HTML 表格格式的跟踪文件
XDEBUG_TRACE_NAKED_FILENAME (8)
通常来说,Xdebug 总是会添加 ".xt" 到文件名末尾,文件名会作为第一个参数传递到这个函数中。 当 XDEBUG_TRACE_NAKED_FILENAME 标志设置,".xt" 不会被添加。(在 Xdebug 2.3 版本中新增)
不像 Xdebug 1,Xdebug 2 不会在内存中储存函数调用,而总是会写入磁盘来减轻内存使用的压力。这些设置 xdebug.collect_includesxdebug.collect_paramsxdebug.collect_return 会影响什么信息会记录到跟踪文件,这个设置 xdebug.trace_format 影响跟踪文件的格式。

这个函数会返回 Xdebug 跟踪的文件名和全路径。这可能会是你传递的文件名(潜在的添加 ".xt"),如果没有文件名传递进去就会是自动生成的文件名。


void xdebug_stop_code_coverage( [int cleanup=1] )
停止代码覆盖

这个函数会停止收集信息,内存中的信息将会被销毁。如果传递 0 作为参数,那么代码覆盖将不会被销毁,以至于可以再次使用 xdebug_start_code_coverage() 函数来继续收集信息。


void xdebug_stop_error_collection()
停止记录由 xdebug_start_error_collection() 开启的所有通知、警告和错误。
在 2.1 版本引入

当函数执行时,由 xdebug_start_error_collection() 开启的错误收集将会停止。这些错误储存在缓存集合区不会被删除,仍然可以通过 xdebug_get_collected_errors 获取到。


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

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


string xdebug_stop_trace()
停止当前函数跟踪

停止跟踪函数调用,关闭跟踪文件。

函数返回跟踪被写入的文件的文件名


float xdebug_time_index()
返回当前的时间索引

返回自脚本开始时的时间索引,以秒为单位。

示例:

<?php
echo xdebug_time_index(), "\n";
for (
$i 0$i 250000$i++)
{
    
// do nothing
}
echo 
xdebug_time_index(), "\n";
?>

返回:

0.00038003921508789
0.76580691337585

void xdebug_var_dump( [mixed var [, ...]] )
显示一个变量细节方面的信息

这个函数显示一个或更多变量的结构化的信息,包含它的类型、值和引用信息。数组是递归性地探测值的。查看变量显示特征的介绍,可以看到 php.ini 的设置如何影响这个函数。

示例:

<?php
ini_set
('xdebug.var_display_max_children');
$c = new stdClass;
$c->foo 'bar';
$c->file fopen'/etc/passwd''r' );
var_dump(
    array(
        array(
TRUE23.14'foo'),
        
'object' => $c
    
)
);
?>  

返回:

array
  0 => 
    array
      0 => boolean true
      1 => int 2
      2 => float 3.14
      more elements...
  'object' => 
    object(stdClass)[1]
      public 'foo' => string 'bar' (length=3)
      public 'file' => resource(3, stream)

 
 
版权所有 © 2002-2019 Derick Rethans
由 Monica 基于 https://xdebug.org/ 翻译,最后修改:2019-08-01
E-mail: MonicaPu2014@Gmail.com
京 ICP 备 16054607 号