php 调试指南(Xdebug版)

欢迎转载,但请在开头或结尾注明原文出处【blog.chaosjohn.com】

(吃透本文,没有人将比你更懂 Php Xdebug 调试

创建一个精简项目(命令行)

创建项目,并且用 composer 安装一个笔者比较喜欢的 微框架,作为示例

$ mkdir debug
$ cd debug
$ composer require mikecao/flight

编写主程序 index.php

cat >> index.php <<EOF
<?php
require 'vendor/autoload.php';

Flight::route('/', function(){
    echo 'hello world!';
});

Flight::start();
EOF

用 php 内置服务器运行项目

$ php -S localhost:8080
[Tue Dec  1 23:31:12 2020] PHP 7.4.13 Development Server (http://localhost:8080) started
[Tue Dec  1 23:31:35 2020] [::1]:57780 Accepted
[Tue Dec  1 23:31:35 2020] [::1]:57780 [200]: GET /
[Tue Dec  1 23:31:35 2020] [::1]:57780 Closing

创建并且运行项目

上面输出的后三行,是在本机另一终端访问 http://localhost:8080 时打印的日志

$ curl -L localhost:8080
hello world!

(使用 php 内置服务器运行项目,只是为了检测项目是否能完好运行;该内置服务器只能用于开发环境,不能用于生产环境)

转移开发至 PhpStorm

JetBrains 公司出品的 PhpStorm 与其安装在此不做赘述。

PhpStorm 中打开项目

PhpStorm 欢迎窗口选择“打开”

打开 偏好设置(mac下快捷键为 Command+, Win/Linux下快捷键为 Ctrl+Alt+s),左边侧边栏定位到 Languages & Frameworks => PHP

打开 PhpStorm 偏好设置

在这里添加此前于 PHPBrew 中安装的 PHP 版本。参考前文 PHPBrew 使用指南(注意:请务必安装 xdebug 扩展:$phpbrew ext install xdebug,否则无法进行调试)

添加 php 解释器

将刚刚添加上的 PHP 版本应用到当前项目


选择 php 解释器

Nginx 运行项目

安装与管理

  • 无视系统环境 - 编译安装,不做赘述
  • macOS
$ brew install nginx
$ brew services start/stop/restart nginx # 启动/停止/重启 nginx
  • Debian / Ubuntu
$ sudo apt update
$ sudo apt install nginx-full
$ sudo systemctl start/stop/restart nginx # 启动/停止/重启 nginx
  • RHEL / CentOS
$ sudo yum update
$ sudo apt install nginx
$ sudo systemctl start/stop/restart nginx # 启动/停止/重启 nginx

配置(本文以 macOSHomebrewNginx 为例)

启动 php-fpm(用 PHPBrew 安装 PHP 时需要包含 +fpm variant)

$ phpbrew fpm start
Starting php-fpm...

在项目根目录下创建 nginx.conf 作为 Nginx 的配置文件

server {
    server_name localhost;
    listen 8000;

    root /Users/chaos/Work/php/demos/debug;

    location / {
        try_files $uri $uri/ /index.php;
        fastcgi_pass unix:/Users/chaos/.phpbrew/php/7.4.13/var/run/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

将该配置文件 软链接 到 Nginx 配置目录下 /usr/local/etc/nginx/servers/

$ ln -sf /Users/chaos/Work/php/demos/debug/nginx.conf /usr/local/etc/nginx/servers/php-debug.conf

检查 nginx.conf 是否有错误

$ nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

启动 Nginx

$ brew services start nginx
==> Successfully started `nginx` (label: homebrew.mxcl.nginx)
Nginx 配置

终端下 curl 访问 Nginx部署的服务,验证项目成功跑了起来

$ curl -L localhost:8000
hello world!

Xdebug 调试

大部分关于 Xdebug 的配置,在前面部分已经配置完毕,我们来验证一下是否配置成功

PhpStorm 顶部菜单栏点击 Run,在下拉菜单中选中 Web Server Debug Validation,弹出窗口中点击底部的 Validate 按钮。

  • 如果显示成功,则调试环境已经搭建完毕
  • 如果显示出错,会给出排错信息


    出错,显示排错信息

发现三处警告,按照排错信息排查,发现问题出在了 Xdebug 3.0.0 版本变动了非常多的地方,导致目前 PhpStorm 最新的稳定版 2020.2.4 对此兼容性欠缺。不过 2020.3 有望解决。

所以笔者将 Xdebug 降级到了 2.X 版本:phpbrew ext install xdebug 2.9.8,再次点击 Validate 按钮,怎么还是一样的报错?

这里我们查看 php-fpm 的信息

$ phpbrew fpm info
...
xdebug support => enabled
Version => 3.0.0
...

所以需要重启一下 php-fpm,让其加载新的 Xdebug 模块

$ phpbrew fpm restart
Stopping php-fpm...
Starting php-fpm...
$ phpbrew fpm info
...
xdebug support => enabled
Version => 2.9.8
...

再次点击 Validate 按钮

2.9.8 依旧报错

依旧报错,不过这里就清晰很多了,照着提示,phpbrew config 直接调用编辑器打开 php.ini 文件,在尾部添加:

[xdebug]
xdebug.remote_enable=1

phpbrew fpm restart 后再次点击 Validate 按钮,成功!

Validate 成功

这就可以愉快的调试部署在 Nginx 里的项目啦,这里我们点击工具栏的 监听按钮,开始监听连接请求

监听请求

浏览器作为请求客户端进行调试

为浏览器安装插件

这里笔者以 Chrome 浏览器为例,安装完后,右键 Xdebug Helper 图标点击 Options 打开选项页,选择 IDE keyPhpStorm

Chrome 下 Xdebug Helper 配置

新开浏览器窗口,地址栏输入localhost:8000访问服务,页面会显示 hello world!。单击 Xdebug Helper 图标,点击 Debug,开启调试模式,至此,图标将会变成绿色(或者使用 Alt+Shift+X 快捷键快速开关 Debug 模式)

切换 Xdebug Helper 到 Debug 模式

准备开始调试:

  1. 确保 PhpStorm监听 按钮已激活
  2. PhpStorm 中给需要调试的代码行打上断点
  3. 确保浏览器的 Xdebug Helper处于 Debug 模式,图标变为绿色
调试准备

刷新浏览器页面,PhpStorm 监听到请求传入,同时浏览器请求处于 Pending 状态,挂起等待请求响应

开始调试

在弹窗中选择完正确的 php 文件后,PhpStorm 就进入了调试模式,成功地停在了断点处,在这里可以查看当前的各项 变量 以及单步运行

PhpStorm断点调试

点击调试窗口左侧的 Resume Program 按钮,程序从断点处恢复运行,至此,浏览器侧的请求收到了等待已久的响应,在窗口渲染出 hello world! 字样

命令行 或其他 请求客户端 发起调试

在实际的纯接口开发场景中,除了类似 localhost:8000 的简单请求,还有诸多带有复杂参数的请求,以及各种 http method 的请求(GET / POST / PUT / HEAD / DELETE / OPTIONS),仅仅通过浏览器地址栏进行发起调试并不能胜任。

开发人品平时发起请求测试,一般都选用 命令行工具(例如 curl / httpie)或类似 Postman 这样的专业请求调试客户端。

通过查阅Xdebug 官方文档,得知,浏览器的插件开启 Debug 模式,仅仅是给当前session增加了一个 Cookie: XDEBUG_SESSION=PHPSTORM

那就简单了,以 curl 举例的三种方式:

  • $ curl -H "Cookie: XDEBUG_SESSION=PHPSTORM" localhost:8000
  • $ curl --cookie XDEBUG_SESSION=PHPSTORM localhost:8000
  • $ curl -b XDEBUG_SESSION=PHPSTORM localhost:8000

Postman 也类似,不再赘述

至此,在 PhpStorm 调试部署在 Nginx 中的项目,杀青!

提出疑问

还记得前面有一张关于配置 php解释器 图么(重新搬运放在本段下方),里面明明配置了 Xdebug 的参数,而 Web Server Debug Validation 还是提示要去 php.ini 中添加 xdebug.remote_enable=1

配置 php 解释器

JetBrains 肯定不会那么无聊,放置一个无用的配置项在这里。那这个配置项究竟对哪块地方生效呢?

PhpStorm 工具栏点击 Add Configuration,点击 + 号,选择 PHP Build-in Web Server,端口改为 8088 (或其他未被占用端口)

PhpStorm 添加配置
PhpStorm 完善配置

选择刚刚新建的 运行配置 php build-in server,点击右侧 绿色三角按钮,运行项目(同时确保 监听按钮 也已激活)

PhpStorm 运行配置

再次在命令行下执行:

$ curl -H "Cookie: XDEBUG_SESSION=PHPSTORM" localhost:8000

Bingo!!! PhpStorm 成功进入了调试状态并且停在了断点处!

发散 1: 在 PhpStorm 调试 远程服务

上文描述的都是调试本地环境,即服务部署在本地 Nginx,通过本地的 php-fpm 调用 php 解释器 进行请求分发处理,“加载”的是本地的 Xdebug(调试端口为默认的 9000),而同时 PhpStorm 也监听本地的 Xdebug9000 端口进行拦截调试。

可往往更多的情况是,服务并不部署在本地,而在 远端服务器,这个时候得如何调试呢?

接下来在 另一台主机(192.168.1.101) 上调试 本机(192.168.1.100) 的服务,来模拟现实开发中的 远程调试

本机(192.168.1.100) 上在 php.ini 尾部添加 xdebug.remote_connect_back=1

另一台主机(192.168.1.101)PhpStorm 点击工具栏上的 监听按钮 开启监听,并且在代码窗口设置断点

该主机(192.168.1.101) 的终端上执行

$ curl -H "Cookie: XDEBUG_SESSION=PHPSTORM" 192.168.1.100:8000

即可看到 PhpStorm 进入了调试模式并且顺利停在了断点处。

发散 2:在 VSCode 中调试 本地服务

打开 VSCode,安装 PHP Debug 扩展

打开项目工程,点击左边栏的 Run,点击 Create a launch.json file,选择 PHP 环境

创建 VSCode 运行配置

VSCode 将会自动创建两个配置:

  • Listen for XDebug:这个配置就是类似 PhpStorm 中的 监听按钮
  • Launch currently open script:执行按照 php-cli 模式运行/调试 当前窗口的php脚本
VSCode 创建的默认运行配置

选择 Listen for XDebug 并点击左侧的 绿色图标 开始运行监听,并且打上断点,命令行下执行 curl --cookie XDEBUG_SESSION=VSCODE localhost:8000,则能看到VSCode 成功进入了调试状态并且停在了断点处。

VSCode 调试模式

发散 3:在 VSCode 调试 远程服务

发散 1 类似,在 另一台主机(192.168.1.101) 上:

  • 确保 php.ini 已添加 xdebug.remote_connect_back=1
  • 选择 Listen for XDebug 并点击左侧的 绿色图标 开始运行监听,并且打上断点
  • 命令行下执行 curl --cookie XDEBUG_SESSION=VSCODE 192.168.1.100:8000 则能看到VSCode 成功进入了调试状态并且停在了断点处。

所以,在 VSCode 调试部署在 Nginx 中的服务(本地与远程),也顺利杀青!

一些 思考疑惑

  1. XdebugIDE key(即使在 php.ini 中配置了 xdebug.idekey=xxx)在 远程调试 时并不起作用,调试请求时在 Cookie 中附加的 XDEBUG_SESSION 设置任意非空字符串都生效。是 Xdebugbug 么?
  2. 无论采用 PhpStorm 还是 VSCode 进行远程调试中,明明远程服务器的 Xdebug 调试端口(默认为9000)对外不可达(仅 localhost 可访问),但是 打上断点 开启监听 又能调试了呢?
  3. 多人协同调试,参考 JetBrains 文档 Multiuser debugging via Xdebug proxies 使用 DBGp代理
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容