Skip to main content

PHP 开启 Xdebug 调试指南

原文地址 https://www.jianshu.com/p/53a9064cb4e7

PHP 开启 xdebug 调试

Xdebug 作为 PHP 的代码调试工具,提供了丰富的调试函数,也可将其配置为 zend studio、editplus、phpstorm 等 IDE 的第三方调试插件。通过开启 Xdebug 的自动跟踪 (auto_trace) 和分析器功能,更可以直观察 PHP 源代码的性能数据,从而优化 PHP 代码。
但无奈 Xdebug 的官方文档的语言是英文,PHP 新手想按照官方文档把 Xdebug 配置好,也并非一件容易之事。本文就是关于 PHP 如何开启 xdebug 调试的一份简单指南,希望越来越多的人都能用上调试利器 Xdebug。

目录

  • Xdebug 调试原理
    • Xdebug调试原理
    • Xdebug通信过程
  • 安装配置 Xdebug
    • 查看本机php版本
    • 安装Xdebug扩展
    • 配置php.ini
  • IDE 配置
    • 配置php-cli
    • 配置Xdebug端口
    • 配置IdeKey
    • 配置servers路径映射
    • 为浏览器生成Start Debugger书签
  • 开启调试
    • 在chrome中点击Start debugger
    • 在PHPSTORM中点击菜单Run->Start Listening for PHP debug connection
    • 浏览器访问本地网站
    • 关闭调试
  • Xdebug 调试中遇到的几个特殊场景
    • 调试局域网内远程主机
    • 跨域调试
    • php脚本调试
    • 调试外网远程主机

一、Xdebug 调试原理

借用官方网站图一张:

Xdebug 调试原理

右边机器(IP=10.0.1.2)是布署了 Nginx/php 的服务端 (下文简称 php 服务端),左侧机器(IP=10.0.1.42)是布署了 IDE(比如 Phpstorm)的 IDE 端 (下文简称 IDE 端)。

调试中基本通信过程说明:

  • 打开浏览器,访问 web 页面,nginx 通过 fastcgi 网关接口加载 PHP 脚本运行 (对应图上第一个朝向右的箭头)。
  • 然后 php 解释器(当然必须已装好 Xdebug 扩展),向 IDE 端的 9000 端口( 本文下面用的都是 9001,原因是我本机 9000 端口被其它程序占用)发起基于 DBGP 协议的调试请求。
  • IDE 端收到 DBGP 协议请求后,就可以开始单步调试了。
  • 调试完成后,服务端 php 解释器执行完毕,向浏览器返回 response。

二、安装配置Xdebug

查看本机 php 版本

$: php --version
PHP 7.0.13-0ubuntu0.16.04.1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
with Zend OPcache v7.0.13-0ubuntu0.16.04.1, Copyright (c) 1999-2016, by Zend Technologies

安装 Xdebug 扩展

去官网 https://xdebug.org/download.php 下载对应版本的 Xdebug。我的操作系统是 ubuntu16.04,所以下载了 source 版本。Xdebug 2.6.0beta1 下载链接

cd xdebug-source-directory
phpize #如果没有,请先安装Php7.0-dev包
which php-config #查找php-config命令的位置
./configure –with-php-config=/usr/bin/php-config
make
make install #可能需要加上sudo
#安装完了,要记一下xdebug.so的安装位置,下面配置php.ini的时候需要

配置 php.ini

[Xdebug]
zend_extension="/usr/lib/php/20151012/xdebug.so"
xdebug.remote_enable=1
#与remote_connect_back不能同时开启
xdebug.remote_host="localhost"
xdebug.remote_port=9001
#与remote_host不能同时开启
;xdebug.remote_connect_back = 1
xdebug.remote_handler="dbgp"
xdebug.idekey=PHPSTORM

解释一下:

  • zend_extension每个人安装 xdebug 扩展的位置可能不同,按实际情况填写。
  • remote_enable 必须设置为 1
  • remote_hostremote_port分别填localhost9001remote是指IDE端,并非浏览器端或者PHP服务端,注意理解清楚。
  • remote_handler只能填dbpg,照填就行。
  • idekey是用于进行会话身份标识的,需要与后面 IDE 端填的保持一致,这里填的是PHPSTORM

三、IDE 配置

配置phpStorm

  • 配置 php-cli

    配置 php-cli

  • 配置 xdebug 端口,我填的是 9001,与前面 php.ini 中xdebug.remote_port保持一致。

    配置 xdebug 端口

  • 配置 IdeKey,与前面 php.ini 中xdebug.idekey保持一致。Host 和 Port 会自动填好。

    配置 IDEKEY

  • 配置 servers,这个下面讲远程调试的时候再讲。

    配置 servers

为浏览器生成 Start Debugger 书签

以 chrome 为例进行说明:

为浏览器生成 Start Debugger 书签

打开https://www.jetbrains.com/phpstorm/marklets/,点击蓝色的 GENERATE 按钮,生成 Start debugger/Stop debugger/ Debug this page 三个蓝色链接后
操作鼠标拖动这三个链接到 chrome 的书签栏上。

到此为止,Xdebug 全部安装配置都完成了。

  • 点击 chrome 书签中的 Start debugger。这个书签的作用就是给页面的 cookie 增加一项XDEBUG_SESSION=PHPSTORM;path=/。Start Debugger 书签实际代码如下:
javascript:(function() {document.cookie='XDEBUG_SESSION='+'PHPSTORM'+';path=/;';})()
  • 打开 Phpstorm,点击菜单Run->Start Listening for PHP debug connection
  • 在需要调试代码的地方打上断点。
  • 打开浏览器访问本地网站。调试起作用了,有木有!!??
  • 如果要关闭调试,先在 chrome 中点击 Stop debugger,然后在 Phpstorm 中点击菜单Run->Stop Listening for PHP debug connection即可。

四、内网远程调试

上面讲的都是一些较简单的场景,但有时候我们也会面临更复杂的场景,比如远程调试、跨域调试、php 脚本调试等等。下面分别讲一下这些复杂场景下如何开启 xdebug 调试。

1)调试局域网内远程主机

调试远程主机,就是 Php 服务端是运行在非本机,但是 IDE 端是安装在我们本机的。举个例子,我本机(IDE 端:192.168.9.28)要调试对方电脑(Php 服务端:192.168.10.210)上的 PHP 代码。

有两种处理方式:

  • 方式一:
    修改 php 服务端192.168.10.210的 php.ini 配置,xdebug.remote_host="192.168.9.28",重启 php-fpm。这样设置的话,只有 192.168.9.28 的上 IDE 能对 Php 服务端进行调试。
  • 方式二:
    注释掉 php 服务端192.168.10.210中 php.ini 的xdebug.remote_host,添加remote_connect_back=1配置,重启 php-fpm。这样设置的话,要求 IDE 端和浏览器端必须在同一台电脑上面,Xdebug 会根据浏览器的 ip 地址确定 IDE 端的 ip 地址,所以可以支持多台电脑同时对 Php 服务端调试。

远程调试的时候,特别地,如果本机电脑代码路径与远程主机代码路径不一样,那么必须配置 Servers 路径映射,方法是 phpstorm->setting->Languages & Frameworks->PHP->Servers。为了省事儿,其实只要配置网站 0.0.0.0 的那一项就可以了。

远程调试 servers mapping

其它操作同上,不再赘述。

2)跨域调试

Xdebug 开启调试需要依赖 cookieXDEBUG_SESSION=PHPSTORM;path=/。但在跨域请求中,浏览器默认并不会传输 cookie, 从而无法开启调试。解决思路也简单,想办法让浏览器在跨域请求中支持带上 cookie 就可以了。

有两种处理方式:

  • 方式一:
  • Php 服务端代码设置允许跨域 cookie,并添加 "Access-Control-Allow-Credentials"="true"
    以 laravel 框架为例,在中间件中添加以下代码:
public function handle($request, Closure $next)
{
return $next($request)
->header("Access-Control-Allow-Credentials", "true")
->header("Access-Control-Allow-Origin", $request->header("Origin"))
->header("Access-Control-Allow-Headers", $request->header("Access-Control-Request->Headers"))
->header("Access-Control-Request-Method", $request->header("Access-Control-Request->Method"));
}

设置的关键点是Access-Control-Allow-Credentials必须设置为true, 从而允许跨域请求时带上相关 cookie。

  • 客户端代码配置,
    以 jQuery.ajax 为例:
$.ajax({
headers:{
"Content-Type":"text/plain",
},
url:url,
type:"POST",
data: bodyText,
dataType:"json",
xhrFields: {
withCredentials: true
},
beforeSend: function(xhr) {
document.cookie = "XDEBUG_SESSION=PHPSTORM;domain=localhost;path=/";
},
async:false,

crossDomain: true,
success:function(res){
},
error:function(err){
},
complete:function(res){
},

})

设置的关键点是在xhrFields中增加withCredentials:true和在beforeSend函数中增加

document.cookie = "XDEBUG_SESSION=PHPSTORM;domain=localhost;path=/";

说明一点:跨域请求开启调试,通过 chrome 书签或者直接修改浏览器 cookie 的方式并不起作用,猜测原因可能是因为浏览器本身的 cookie 和 XmlHttpRequest 中的 cookie 并不是一回事儿。

  • 方式二
  • 借助 nginx,开启跨域调试 (大招来啦!)
    现在大部分 Phper 开发的环境都是 LNMP,那么我们可以请 nginx 帮忙修改 cookie,从而将 cookie 传输到 php 服务端。
    nginx 默认不支持修改请求的 header 字段,我们需要下载安装headers-more-nginx-module扩展,下载地址 https://github.com/openresty/headers-more-nginx-module
    PS:给 nginx 安装扩展不再赘述了哦。不会的话,自己百度下吧。
  • 修改 nginx.conf 虚拟主机配置,如下所示:
more_set_input_headers  "Cookie:XDEBUG_SESSION=PHPSTORM; $http_cookie";

其它操作同上,不再赘述。

3)php 脚本调试

有两种处理方式:

  • 方式一:
    打开 Phpstorm,找到 myscript.php 文件,点击右键Debug 'myscript.php'即可。
  • 方式二:
    修改环境变量也可以开启 Xdebug 调试
export XDEBUG_CONFIG="XDEBUG_SESSION=PHPSTORM"
php myscript.php

4)调试外网远程主机

分为如下几步:

  • 设置内网穿透,用的是花生壳,我将花生壳分配的域名和端口指向我本机 IP192.168.9.28 和本机 9001 端口。

    内网穿透端口映射. png

PS:如果觉得内网穿透麻烦的话,也可以使用 ssh 来实现同样的功能,而且是免费的。
参见我写的另一篇文章利用 ssh 隧道,进行外网 php xdebug 调试和 nodejs 调试

  • 修改远端主机 php-fpm 的 php.ini 的 xdebug 部分如下:
[Xdebug]
zend_extension="/usr/lib/php/20151012/xdebug.so"
xdebug.remote_enable=1
#mzxxxxxxxxxxxxxpc.cn就是内网穿透映射中提供的域名
xdebug.remote_host="mzxxxxxxxxxxxxxpc.cn"
#4xxxx2就是内网穿透映射提供的端口
xdebug.remote_port=4xxxx2
xdebug.remote_handler="dbgp"
xdebug.idekey=PHPSTORM
  • 重启 php-fpm
service php7.0-fpm restart
  • openresty 或者 nginx 的 server 块中添加以下配置,开启 xdebug session。
more_set_input_headers  "Cookie:XDEBUG_SESSION=PHPSTORM; $http_cookie";

如果不愿意用 openresty 的方式,那么点击浏览器标签start-debugger也可开启 xdebug session

  • 本机 IDE 添加 serverMapping 映射

    serverMapping 映射. png

  • 新建一个运行调试 php_webApplication 的任务

    image

新建 php web application.png

  • 最后一步,打上断点,点击菜单上RUN=>debug xxx web Application,就可以开启调试了。
  • 遗留问题:外网远程调试,必须点击菜单上的RUN=>debug xxx web Application才能正常进行调试,其它方式打开网站的话,调试总是会出各种各样的问题。

Xdebug 开启调试的配置就这么简单。。。