xdebug

https://xdebug.org/
Xdebug is an extension for PHP to assist with debugging and development. It contains a single step debugger to use with IDEs; it upgrades PHP’s var_dump() function; it adds stack traces for Notices, Warnings, Errors and Exceptions; it features functionality for recording every function call and variable assignment to disk; it contains a profiler; and it provides code coverage functionality for use with PHPUnit.

Xdebug作为PHP的代码调试工具,提供了丰富的调试函数,也可将其配置为zend studio、editplus、phpstorm等IDE的第三方调试插件。通过开启Xdebug的自动跟踪(auto_trace)和分析器功能,更可以直观察PHP源代码的性能数据,从而优化PHP代码。

右边机器(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扩展
去官网https://xdebug.org/download.php下载对应版本的Xdebug。



配置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_host和remote_port分别填localhost和9001。remote是指IDE端,并非浏览器端或者PHP服务端,注意理解清楚。
remote_handler只能填dbpg,照填就行。
idekey是用于进行会话身份标识的,需要与后面IDE端填的保持一致,这里填的是PHPSTORM。
三、IDE配置
以Phpstorm为例子说明。
配置php-cli
配置xdebug端口,我填的是9001,与前面php.ini中xdebug.remote_port保持一致。

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



配置servers
为浏览器生成Start Debugger书签
以chrome为例进行说明:
打开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:(/** @version 0.5.2 */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即可。
五、几个特殊场景的Xdebug调试
上面讲的都是一些较简单的场景,但有时候我们也会面临更复杂的场景,比如远程调试、跨域调试、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的那一项就可以了。



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”) //这里不能使用逻辑值true,只能使用字符串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端口。



PS:如果觉得内网穿透麻烦的话,也可以使用ssh来实现同样的功能,而且是免费的。



修改远端主机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



openresty或者nginx的server块中添加以下配置,开启xdebug session。
more_set_input_headers “Cookie:XDEBUG_SESSION=PHPSTORM; $http_cookie”;
如果不愿意用openresty的方式,那么点击浏览器标签start-debugger也可开启xdebug session



本机IDE添加serverMapping映射



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



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



php.ini添加xdebug模块
phpstorm配置xdebug支持
google chrome添加phpstorm支持、debug调试
postman添加cookie,支持断点调试
php.ini添加xdebug模块
在php.ini文件添加xdebug配置参数



[xdebug]
zend_extension =”D:/wamp64/bin/php/php7.0.23/zend_ext/php_xdebug-2.5.5-7.0-vc14-x86_64.dll” # xdebug 下载链接(https://xdebug.org/download.php),wamp集成环境会自带xdebug插件
xdebug.remote_enable = On # 开启远程调试
xdebug.profiler_enable = On
xdebug.profiler_enable_trigger = On
xdebug.profiler_output_name = cachegrind.out.%t.%p
xdebug.profiler_output_dir =”D:/wamp64/tmp”
xdebug.show_local_vars=0

xdebug.idekey=PHPSTORM # 非常重要,务必记住
xdebug.remote_enable = On

xdebug.remote_host=localhost

xdebug.remote_port=9000 # 端口ID,phpstorm 设置须一致
xdebug.remote_handler=dbgp



DBGP proxy设置
postman 添加 cookie
postman搭建xdebug并测试成功,下面介绍使用google chrome请求
安装 phpstorm helper 插件



安装debug插件



下载链接 phpstorm helper 插件 (https://www.crx4chrome.com/crx/768/)



下载xdebug(https://www.crx4chrome.com/crx/1716/)



第一个按钮:step over 步越
执行当前函数的下一步,如果有子函数,也不会进入,会一直执行到函数结束



第二个按钮:step into 步入
执行当前函数的下一步,如果有子函数,会从头到尾执行子函数,还原了程序执行的最详细的路线,从构造函数到结尾的每一步都会跳到。



第三个按钮:force step into
与step into 相同,执行当前函数的下一步,如果有子函数也会进入子函数,只不过不会从头到尾的还原函数执行的路线,会直接跳到子函数内第一步,构造函数等一些前置方法会忽略



第四个按钮:step out 步出
跳出当前执行的函数,跳到父函数的下一步。



第五个按钮:run to cursor 
执行到下一个断点处



Xdebug是PHP的扩展,用于协助调试和开发。



它包含一个用于IDE的调试器
它升级了PHP的var_dump()函数
它为通知,警告,错误和异常添加了堆栈跟踪
它具有记录每个函数调用和磁盘变量赋值的功能
它包含一个分析器
它提供了与PHPUnit一起使用的代码覆盖功能。
猿生必备的工具。
但不推荐在生产环境中使用xdebug,因为他太重了。



安装
PECL 安装
pecl install xdebug
zend_extension=”/usr/local/php/modules/xdebug.so”
源码包安装
https://xdebug.org/download.php 寻找对应的包



wget xxx.gz
./configure
make && make install
zend_extension=”/usr/local/php/modules/xdebug.so”
Docker安装
以下为php dockerfile内部分内容



RUN pecl install xdebug
RUN echo ‘zend_extension=xdebug.so’ » /usr/local/etc/php/conf.d/xdebug.ini
工作原理
IDE(如PHPStorm)已经集成了一个遵循BGDP的XDebug插件,当开启它的时候, 会在本地开一个XDebug调试服务,监听在调试器中所设置的端口上,默认是9000,这个服务就会监听所有到9000端口的链接。



当浏览器发送一个带 XDEBUG_SESSION_START 的参数的请求到服务器时,服务器接受后将其转到后端的php处理,如果php开启了XDebug模块,则会将debug信息转发到客户端IP的IDE的调试端口上。



当参数或者cookie信息中不带 XDEBUG_SESSION_START ,则不会启动调试。这就为后续在浏览器中添加开关提供了可能。



具体内容请移步官网 https://xdebug.org/docs/basic



Xdebug将替换PHP的var_dump()函数来显示变量。Xdebug版本包含了不同类型的不同颜色,并对数组元素/对象属性的数量、最大深度和字符串长度进行了限制。还有一些其他函数也处理变量显示。



名称 类型 默认值 注解
xdebug.cli_color integer 0 cli模式下输入结果是否设置颜色
xdebug.overload_var_dump boolean 2 是否允许xdebug重载var_dump函数
xdebug.var_display_max_children integer 128 var_dump 对数组对象子级的显示层数限制
xdebug.var_display_max_data integer 512 var_dump 对结果长度的限制
xdebug.var_display_max_depth integer 3 var_dump 对默认显示嵌套的层数的限制
具体内容请移步官网 https://xdebug.org/docs/display



堆栈跟踪配置
当Xdebug被激活时,当PHP决定显示一个通知、警告、错误等时,它将显示一个堆栈跟踪。堆栈跟踪显示的信息以及它们的显示方式可以配置为适合您的需要。



名称 类型 默认值 注解
xdebug.cli_color integer 0 cli模式下输入结果是否设置颜色
xdebug.collect_includes boolean 1 控制Xdebug是否应该将include()、include_once()、require()或require_once()中的文件名写入跟踪文件
xdebug.collect_params integer 0 该设置默认为0,控制当函数跟踪或堆栈跟踪记录函数调用时,Xdebug是否应该收集传递给函数的参数
xdebug.collect_vars boolean 0 这个设置告诉Xdebug在特定范围内使用哪些变量。由于Xdebug必须逆向工程PHP的操作码数组,这种分析可能相当缓慢。对于使用xdebug.collect_params,此设置不会记录不同变量的值。只有当您希望使用xdebug_get_declared_vars()时,才需要启用此设置。
xdebug.dump.* string empty * 可以是任何COOKIE、文件、GET、POST、REQUEST、SERVER、SESSION。这七个设置控制在发生错误时显示来自超全局变量的哪些数据。
xdebug.dump_globals boolean 1 当该设置设置为true时,Xdebug将添加通过Xdebug.dump配置的超级全局变量的值*到屏幕上的堆栈跟踪和错误日志。
xdebug.dump_once boolean 1 控制是否应该在所有错误情况(设置为0)上转储超全局变量的值,或只在第一个错误情况下转储超全局变量的值(设置为1)
xdebug.dump_undefined boolean 0 如果您想从超全局变量中转储未定义的值,您应该将该设置设置为1,否则将其设置为0。
xdebug.file_link_format string 文件链接格式
具体内容请移步官网 https://xdebug.org/docs/stack…



函数调试配置
Xdebug允许记录所有函数调用,包括参数和以不同格式返回的值。



名称 类型 默认值 注解
xdebug.auto_trace boolean 0 当将此设置设置为ture时,将在脚本运行之前启用函数调用的跟踪
xdebug.collect_assignments boolean 0 该设置默认为0,控制Xdebug是否应该向函数跟踪添加变量赋值。
xdebug.collect_includes boolean 1 该设置默认为1,控制Xdebug是否应该将include()、include_once()、require()或require_once()中的文件名写入跟踪文件。
xdebug.collect_params integer 0 该设置默认为0,控制当函数跟踪或堆栈跟踪记录函数调用时,Xdebug是否应该收集传递给函数的参数。
xdebug.collect_return boolean 0 该设置默认为0,控制Xdebug是否应该将函数调用的返回值写入跟踪文件。
xdebug.show_mem_delta integer 0 Xdebug生成的跟踪文件将显示函数调用之间内存使用的差异
xdebug.trace_format integer 0 跟踪文件的格式
xdebug.trace_options integer 0 当设置为“1”时,跟踪文件将被附加到后面的请求中,而不是被覆盖。
xdebug.trace_output_dir string /tmp 写入跟踪文件的目录,确保PHP运行的用户具有该目录的写权限。
具体内容请移步官网 https://xdebug.org/docs/execu…



垃圾收集统计信息
Xdebug的内置垃圾收集统计信息分析器允许您查明PHP内部垃圾收集器何时触发、它能够清理多少变量、它花费了多长时间以及实际释放了多少内存。



名称 类型 默认值 注解
xdebug.gc_stats_enable bool false 如果启用此设置,则垃圾收集运行的统计信息将自动收集到使用xdebug.gc_stats_output_dir设置的给定目录中, 并使用由xdebug.gc_stats_output_name配置的自动生成的名称。
xdebug.gc_stats_output_dir string /tmp 将写入垃圾收集统计信息输出的目录,确保将运行PHP的用户具有对该目录的写入权限。无法使用ini_set() 在脚本中设置此设置。
xdebug.gc_stats_output_name string gcstats.%p 此设置确定用于将垃圾回收统计信息转储到的文件的名称。该设置使用格式说明符指定格式,与sprintf() 和strftime() 非常相似。有几种格式说明符可用于格式化文件名。
具体内容请移步官网 https://xdebug.org/docs/garba…



远程调试配置
Xdebug为与运行PHP脚本交互的调试器客户机提供了一个接口。



名称 类型 默认值 注解
xdebug.extended_info integer 1 控制Xdebug是否应该为PHP解析器强制执行’extended_info’模式; 这允许Xdebug使用远程调试器执行文件/行断点。在跟踪或分析脚本时,您通常希望关闭此选项,因为PHP生成的oparray将增加大约三分之一的大小,从而减慢脚本速度。无法使用ini_set()在脚本中设置此设置,但只能在php.ini中设置。
xdebug.idekey string complex 控制哪些IDE Key Xdebug应传递给DBGp调试器处理程序。则与客户端通信的key
xdebug.remote_addr_header string “” 该值将用作$SERVER超全局数组中的键,以确定用于查找用于“连接回”的IP地址或主机名的标头
xdebug.remote_autostart boolean 0 您需要使用特定的HTTP GET / POST变量来启动远程调试
xdebug.remote_connect_back boolean 0 如果你不设置ip地址,就只能靠xdebug自己找了,Xdebug将尝试连接到发出HTTP请求的客户端。它检查$_SERVER[‘HTTP_X_FORWARDED_FOR’]和$_SERVER[‘REMOTE_ADDR’]变量以找出要使用的IP地址
xdebug.remote_cookie_expire_time integer 3600 设置cookie的生命周期
xdebug.remote_enable boolean 0 是否开启远程调试
xdebug.remote_handler string dbgp 调试的通信协议
xdebug.remote_host string localhost 调试的网络地址,开启了remote_connect_back后,当前配置就无效了
xdebug.remote_log string 调试的日志
xdebug.remote_port integer 9000 调试的端口
xdebug.remote_timeout integer 200 调试的通信链接的等待时间
具体内容请移步官网 https://xdebug.org/docs/remote



官方链接
全部配置请移步官网 https://xdebug.org/docs/all_s…
全部函数请移步官网 https://xdebug.org/docs/all_f…



PHPSTORM DEBUG
网络上的配置DEBUG文章太杂太乱,在PHPSTROM跳来跳去的,实在让人心烦意乱,本章重新整理描述。



配置
其实在PHPSTROM中已经出了很详细的教程,是吧?只不过大部分人都会直接百度/Google,查询是个好习惯,但要视情况而定。



Languages & Frameworks > PHP > Debug
clipboard.png



第一步
下载XDEBUG扩展,本章开头已经讲过了,这里不再阐述。
在安装完成后,PHPSTROM提供了验证脚本。脚本地址为 https://gist.github.com/litzi…
正常情况下检测成功的样子是



clipboard.png



看到这个你就可以放心的去debug了。



第二步
装个浏览器插件,用户请求监听。这个东西唯一的作用就是方便了debug,正常如果不安装的话你需要通过GET传参 XDEBUG_SESSION_START=ID_KEY 才可以,安装插件后就不需要了。



clipboard.png



你可以自行选择是否开启debug,以下为浏览器插件列表



浏览器 下载
Chrome Xdebug Helper
Firefox The easiest Xdebug or Xdebug Helper
Safari Xdebug Toggler
Opera Xdebug launcher
Internet Explorer PhpStorm bookmarklets generator
第三步
开启监听即可。



clipboard.png



你可以直接点击图片上的监听按钮。



到现在为止,就配置好了IDE。



第四步
创建DEBUG配置文件,根据每个项目都要配置。这步你跑不了。



clipboard.png



你看,PHPSTORM非常人性化,在每一步都会给你出个简单的教程来描述如何配置DEBUG。



添加一个Server和IDE key(xdebug.idekey) 就可以进行调试了。



总结
总结以下IDE配置DEBUG的步骤,实际很简单。



下载安装debug
验证是否通信正常
添加浏览器插件 (可省略)
配置运行文件
愉快的debug
这里还要说明下,如果你是不需要访问本机调试一些类或者代码块,你只需要在本机上安装好XDEBUG,上述配置全部省略,直接点小虫子图标即可调试。DEBUG端口默认是9000,如果配置文件内修改了,当然在IDE内也需要修改下。
调试
介绍下实际DEBUG过程中PHPSTORM面板的按钮都是做什么用的。当你启动监听后,你将会看到如下图



clipboard.png



根据上图图标位置,以x,y坐标的方式描述每个图标的功能。



图标 位置 (x,y) 功能
clipboard.png
0,0 重新执行DEBUG (Rerun test.php)
clipboard.png
0,1 跳转到原调试文件 (Show execution point)
clipboard.png
0,2 跳到下一行 (Step over)
clipboard.png
0,3 执行下一步 (Step info)
clipboard.png
0,4 跳入库、构造函数等方法或类中 (Force Step Info)
clipboard.png
0,5 执行函数体或类方法,如果在最外层则结束本次调试 (Step out)
clipboard.png
0,6 跳到当前节点的下个断点 (Run to Cursor)
clipboard.png
0,7 执行修改变量或返回的结果用于二次调试(Evaluate arbitrary expression)
clipboard.png
0,8 显示值的地址 (Show Values Addresses)
clipboard.png
0,9 是否显示空的值 , 默认是不显示
clipboard.png
0,10 跳到下个断点 (Add method to skip list)
clipboard.png
1,0 重新执行DEBUG (Resume Program)
clipboard.png
2,0 停止DEBUG(Step process)
clipboard.png
3,0 查看和管理所有的断点 ( View and manage all breakpoints)
clipboard.png
4,0 忽略所有断点 (Mute breakpoints)
其他
Docker PHP XDEBUG
部分人在本机装了Docker,容器中运行这PHP,这个时候该如何进行DEBUG呢?如果认真看本篇文章,你会发现十分的简单。本身XDEBUG就是远程调试。首先你要保证



容器做了端口映射到本机80
容器内项目目录做了磁盘挂载
将容器PHP XDEBUG 中



xdebug.remote_host=local_ip
即可,也不用担心hosts文件的问题



本机IP = 127.0.0.1 = localhost
这样配置完成后,就可以当容器不存在,与本机调试一样。



ebug是PHP开发中两个常用的断点调试工具之一(另一个为Zend Debugger)。


Category php