vscode使用xdebug3调试PHP脚本

606 阅读6分钟

本地环境windows

php -i 
Architecture => x86
PHP Extension Build => API20170718,NTS,VC15

php -v 
7.2.1

xdebug 3.0.1

PHP Version: PHP version 8.0.99 or older
PHP Version: PHP 7.2.0 or newer
PEAR Package: PEAR 1.9.1 or newer

于是下载:https://windows.php.net/downloads/pecl/releases/xdebug/3.0.1/php_xdebug-3.0.1-7.2-nts-vc15-x86.zip
解压后将 php_xdebug.dll 复制到 ext 目录下。

修改 php.ini 文件 
[XDebug]
zend_extension="D:\phpStudy\PHPTutorial\php\php-7.2.1-nts\ext\php_xdebug.dll"
xdebug.output_dir="D:\phpStudy\PHPTutorial\tmp\xdebug"
xdebug.start_with_request = yes
xdebug.mode = debug
xdebug.client_host = 127.0.0.1
xdebug.client_port = 9100

注意,xdebug3 和 xdebug2 的配置项发生了很大变化,尽量参考官方说明而不是网上copy。

文档:xdebug.org/docs/all_se…

php -m 
php --ri xdebug

vscode安装 PHP Debug 插件。

打开settings.json配置PHP执行程序:
"php.validate.executablePath": "D:/phpStudy/PHPTutorial/php/php-7.2.1-nts/php.exe",

创建 launch.js 文件
在这里插入图片描述
如果已经存在了就修改
在这里插入图片描述
只需要将两个 port 修改为 9100 即可。

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9100
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9100
        }
    ]
}

新建测试文件 test.php

<?php
ini_set('date.timezone', 'Asia/Shanghai');

$url = 'http://220.249.103.107:20780/job-work';

$headerArr = array(
    'x-token: MS8QttKgHtXT6ZbP'
);

echo date('Y-m-d H:i:s', 1596211200);
echo PHP_EOL;
echo date('Y-m-d H:i:s', 1604160000);

选择 Launch currently open script,也就是 launch.js 中的第二个配置
在这里插入图片描述
至此准备工作已经就绪,开始在 test.php 打断点,最后按 F5 或者点击上面的绿色箭头启动调试,最下面的横条会变成黄色,效果如下:
在这里插入图片描述
按 F5 下一步。

嗯?为什么没看见输出呢,那是因为没有打开调试控制台
在这里插入图片描述
在调试模式下,将鼠标放在变量上可以看到变量的值,当然,左边也会列出变量的值
在这里插入图片描述
xdebug.mode = debug 的使用场景是当你需要断点调试的时候,但是有时候程序没问题,你想看看性能和各个地方的耗时情况,此时你可以换成 trace 和 profile 模式。

记录 trace ,也就是函数调用链,修改 php.ini
xdebug.mode = trace

还是上面的脚本,去掉所有的断点(当然也可以不去掉但是你需要一直按 F5 直到程序跑完),此时按一下 F5 程序就跑完了,然后去到目录D:\phpStudy\PHPTutorial\tmp\xdebug也就是上面配置的目录,会看到多出了一个文件 trace.1480951438.xt,内容为:

TRACE START [2020-12-30 06:47:20.891508]
    0.0782     383264   -> {main}() D:\dev\php\my\test.php:0
    0.0784     383264     -> ini_set($varname = 'date.timezone', $newvalue = 'Asia/Shanghai') D:\dev\php\my\test.php:2
    1.3640     383536     -> getstr() D:\dev\php\my\test.php:15
    1.9238     383536       -> rand($min = 0, $max = 25) D:\dev\php\my\test.php:6
    2.2915     383536     -> date($format = 'Y-m-d H:i:s', $timestamp = 1596211200) D:\dev\php\my\test.php:17
    3.0697     384248     -> date($format = 'Y-m-d H:i:s', $timestamp = 1604160000) D:\dev\php\my\test.php:19
    3.0722     313408
TRACE END   [2020-12-30 06:47:23.885604]

另外你还可以记录 profile ,用以性能分析,修改 php.ini
xdebug.mode = profile

于是多出了一个文件 cachegrind.out.241668,内容为

version: 1
creator: xdebug 3.0.1 (PHP 7.2.21)
cmd: D:\dev\php\my\test.php
part: 1
positions: line

events: Time_(10ns) Memory_(bytes)

fl=(1) php:internal
fn=(1) php::ini_set
2 9970 272

fl=(1)
fn=(2) php::rand
6 1170 0

fl=(2) D:\dev\php\my\test.php
fn=(3) getstr
4 52017740 0
cfl=(1)
cfn=(2)
calls=1 0 0
6 1170 0

fl=(1)
fn=(4) php::date
17 7210 936

fl=(1)
fn=(4)
19 1200 256

fl=(2)
fn=(5) {main}
1 455536270 0
cfl=(1)
cfn=(1)
calls=1 0 0
2 9970 272
cfl=(2)
cfn=(3)
calls=1 0 0
15 52018910 0
cfl=(1)
cfn=(4)
calls=1 0 0
17 7210 936
cfl=(1)
cfn=(4)
calls=1 0 0
19 1200 256

summary: 507821490 418632

那么如何从这个文件分析出程序的性能呢?由于篇幅过长,我写到了另外一篇文章来讲这个 blog.csdn.net/raoxiaoya/a…

在本地开发的时候,一般会同时开启两个,即
xdebug.mode = debug,profile

xdebug只会在你的编辑器中启动了调试模式的情况下才会工作。

经过前面的过程,在vscode调试PHP脚本已经很容易了,那么,可不可以调试http请求呢?当然是可以的。
此处还是以断点调试为例,即 debug 模式。

还是刚才的 test.php 文件,打上断点,调试模式选择 Listen for XDebug
在这里插入图片描述
此时在编辑区中的调试控制条没法点击下一步了。

命令行进入 test.php 所在的目录,启动php内置的web服务器 php -S localhost:8000
在这里插入图片描述
在浏览器中访问 http://localhost:8000/test.php
在这里插入图片描述
浏览器处于转圈状态,vscode开始闪烁,切换到vscode发现调试已被激活,此时可以按 F5 来逐步调试了。
在这里插入图片描述
直到调试完,浏览器才有输出,这和输出缓冲区有关系就不在这里说了。同样的,如果只想分析性能就不用打断点了,让它执行完再去分析xdebug日志文件。

在使用浏览器这种方式调试的过程中发现一个问题,只有第一次请求才会生成 cachegrind.out 文件,后面的请求并不会去更新此文件,即使我改了代码,暂时不知道什么原因。

关于在PHPStorm中使用xdebug可以参考 blog.csdn.net/qq_34087545…

关于XDebug的运行原理

根据上面的两种调试情况,我画了一个简易流程图。
在这里插入图片描述

关于xdebug3配置:

xdebug.mode

此设置控制启用哪些Xdebug功能。

此设置只能在PHP进程启动时(直接或通过php-fpm)在php.ini或99-xdebug.ini读取的文件中进行设置,而不能在.htaccess和 .user.ini按请求读取的文件中进行设置。

接受以下值:

  • off
    没有启用任何功能。Xdebug除了检查功能是否已启用外不起作用。如果您想要接近零的开销,请使用此设置。
  • develop
    启用包括重载的var_dump()在内的开发帮助。
  • coverage
    使Code Coverage Analysis能够生成代码覆盖率报告,主要是与PHPUnit结合使用 。
  • debug
    启用步骤调试。这可用于在代码运行时逐步检查代码,并分析变量的值。
  • gcstats
    使垃圾收集统计信息能够收集有关PHP的垃圾收集机制的统计信息。
  • profile
    启用性能分析,您可以使用它通过KCacheGrind之类的工具分析性能瓶颈。
  • trace
    启用功能跟踪功能,该功能允许您记录每个函数调用,包括参数,变量赋值以及在对文件的请求期间进行的返回值。

您可以通过以逗号分隔xdebug.mode:的值作为标识符来同时启用多个模式xdebug.mode=develop,trace。
您还可以通过XDEBUG_MODE在命令行上设置环境变量来设置模式。这将优先于xdebug.mode 设置。

client_port

Xdebug’s default debugging port has changed from 9000 to 9003.

start_with_request

我们直到在CLI模式下,PHP脚本可以被轻松的调试,但是在fastcgi模式下,xdebug在何种情况拦截请求并触发调试呢,实际上一套WEB API 只有极少有性能瓶颈的API才需要被debug,每个接口都去记录profile是没必要的。这就是此配置的意义:

  • yes
    该功能在PHP请求启动时以及运行任何PHP代码之前启动。例如,xdebug.mode = trace 和 xdebug.start_with_request = yes启动整个请求的功能跟踪。
  • no
    请求开始时,该功能未激活。你仍然可以调用函数xdebug_start_trace() 来启动 trace;调用xdebug_break()开始逐步调试;调用xdebug_start_gcstats()来做垃圾收集统计。
  • trigger
    仅当请求开始时存在特定触发条件时,才激活该功能。触发器的名称是(大写)XDEBUG_TRIGGER,而Xdebug会去检查一下变量中($_ENV,$_GET,$_POST,$_COOKIE)是否有这个字段。
    功能特定的触发器名称也有一个旧式的备用名称:(XDEBUG_PROFILE 对于 Profiling),(XDEBUG_TRACE 对于 Function Trace)和 (XDEBUG_SESSION 对于 Step Debugging)
    也可以通过进行步骤调试的调试会话管理XDEBUG_SESSION_START
    使用xdebug.trigger_value可以控制哪个特定的触发器值将激活该触发器。如果xdebug.trigger_value设置为空字符串,则将接受任何值。
    示例:http://localhost:8000/test.php?XDEBUG_TRIGGER
  • default
    该default值取决于xdebug.mode
    debug:trigger
    gcstats:no
    profile:yes
    trace:trigger