PHP开启Xdebug调试指南
<blockquote><p>Xdebug作为PHP的代码调试工具,提供了丰富的调试函数,也可将其配置为zend studio、editplus、phpstorm等IDE的第三方调试插件。通过开启Xdebug的自动跟踪(auto_trace)和分析器功能,更可以直观察PHP源代码的性能数据,从而优化PHP代码。<br>
但无奈Xdebug的官方文档的语言是英文,PHP新手想按照官方文档把Xdebug配置好,也并非一件容易之事。本文就是关于PHP如何开启xdebug调试的一份简单指南,希望越来越多的人都能用上调试利器Xdebug。</p>
</blockquote>
<h2>一、Xdebug调试原理</h2>
<hr>
<p><em>借用官方网站图一张:</em><br>
</p>
<div class="image-package">
<div class="image-container" style="max-width: 582px; max-height: 222px">
<div class="image-view" data-width="582" data-height="222"><img src="https://upload-images.jianshu.io/upload_images/5394123-d3a83c3dcaddf614.gif?imageMogr2/auto-orient/strip|imageView2/2/w/582"></div>
</div>
<div class="image-caption">Xdebug调试原理</div>
</div>
<p>
<br>
右边机器(IP=10.0.1.2)是布署了Nginx/php的服务端(下文简称php服务端),左侧机器(IP=10.0.1.42)是布署了IDE(比如Phpstorm)的IDE端(下文简称IDE端)。</p>
<p><strong>调试中基本通信过程说明:</strong></p>
<blockquote>
<ul>
<li>打开浏览器,访问web页面,nginx通过fastcgi网关接口加载PHP脚本运行 (对应图上第一个朝向右的箭头)。</li>
<li>然后php解释器(当然必须已装好Xdebug扩展),向IDE端的9000端口( 本文下面用的都是9001,原因是我本机9000端口被其它程序占用)发起基于DBGP协议的调试请求。</li>
<li>IDE端收到DBGP协议请求后,就可以开始单步调试了。</li>
<li>调试完成后,服务端php解释器执行完毕,向浏览器返回response。</li>
</ul>
</blockquote>
<h1>二、安装配置Xdebug</h1>
<hr>
<ul>
<li><strong>查看本机php版本</strong></li>
</ul>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">$: 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
</code></pre>
<ul>
<li> <strong>安装Xdebug扩展</strong><br>
去官网https://xdebug.org/download.php下载对应版本的Xdebug。我的操作系统是ubuntu16.04,所以下载了source版本。<em>Xdebug 2.6.0beta1下载链接</em>
</li>
</ul>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">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的时候需要
</code></pre>
<ul>
<li><strong>配置php.ini</strong></li>
</ul>
<pre class="line-numberslanguage-ini"><code class="inilanguage-ini">
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
</code></pre>
<p><em>解释一下:</em></p>
<ul>
<li><code>zend_extension</code>每个人安装xdebug扩展的位置可能不同,按实际情况填写。</li>
<li><code>remote_enable</code> 必须设置为1</li>
<li><code>remote_host</code>和<code>remote_port</code>分别填<code>localhost</code>和<code>9001</code>。<code>remote</code>是指<code>IDE端</code>,并非<code>浏览器端</code>或者<code>PHP服务端</code>,注意理解清楚。</li>
<li><code>remote_handler</code>只能填<code>dbpg</code>,照填就行。</li>
<li><code>idekey</code>是用于进行会话身份标识的,需要与后面IDE端填的保持一致,这里填的是<code>PHPSTORM</code>。</li>
</ul>
<h2>三、IDE配置</h2>
<hr>
<p>以Phpstorm为例子说明。</p>
<ul>
<li>
<p>配置php-cli</p>
<br>
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 339px">
<div class="image-view" data-width="1074" data-height="339"><img src="https://upload-images.jianshu.io/upload_images/5394123-c401ff59a6b27338.png?imageMogr2/auto-orient/strip|imageView2/2/w/1074"></div>
</div>
<div class="image-caption">配置php-cli</div>
</div>
</li>
<li>
<p>配置xdebug端口,我填的是9001,与前面php.ini中<code>xdebug.remote_port</code>保持一致。<br>
</p>
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 531px">
<div class="image-view" data-width="1033" data-height="531"><img src="https://upload-images.jianshu.io/upload_images/5394123-d71d2d7347800819.png?imageMogr2/auto-orient/strip|imageView2/2/w/1033"></div>
</div>
<div class="image-caption">配置xdebug端口</div>
</div>
</li>
<li>
<p>配置IdeKey,与前面php.ini中<code>xdebug.idekey</code>保持一致。Host和Port会自动填好。<br>
</p>
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 393px">
<div class="image-view" data-width="1093" data-height="393"><img src="https://upload-images.jianshu.io/upload_images/5394123-715d1958ffe7ff77.png?imageMogr2/auto-orient/strip|imageView2/2/w/1093"></div>
</div>
<div class="image-caption">配置IDEKEY</div>
</div>
</li>
<li>
<p>配置servers,这个下面讲远程调试的时候再讲。</p>
<br>
<div class="image-package">
<div class="image-container" style="max-width: 425px; max-height: 216px">
<div class="image-view" data-width="425" data-height="216"><img src="https://upload-images.jianshu.io/upload_images/5394123-a4fec1a49d287429.png?imageMogr2/auto-orient/strip|imageView2/2/w/778"></div>
</div>
<div class="image-caption">远程调试servers mapping</div>
</div>
</blockquote>
<p>其它操作同上,不再赘述。</p>
<h5>2)<strong>跨域调试</strong>
</h5>
<blockquote>
<p>Xdebug开启调试需要依赖cookie<code>XDEBUG_SESSION=PHPSTORM;path=/</code>。但在跨域请求中,浏览器默认并不会传输cookie, 从而无法开启调试。解决思路也简单,想办法让浏览器在跨域请求中支持带上cookie就可以了。</p>
</blockquote>
<p>有两种处理方式:</p>
<ul>
<li><strong>方式一:</strong></li>
</ul>
<blockquote>
<ul>
<li>Php服务端代码设置允许跨域cookie,并添加"Access-Control-Allow-Credentials"="true"<br>
以laravel框架为例,在中间件中添加以下代码:</li>
</ul>
<pre class="line-numberslanguage-php"><code class="phplanguage-php"><span class="token keyword">public <span class="token keyword">function <span class="token function">handle<span class="token punctuation">(<span class="token variable">$request<span class="token punctuation">, Closure <span class="token variable">$next<span class="token punctuation">)
<span class="token punctuation">{
<span class="token keyword">return <span class="token variable">$next<span class="token punctuation">(<span class="token variable">$request<span class="token punctuation">)
<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Allow-Credentials"<span class="token punctuation">, <span class="token double-quoted-string string">"true"<span class="token punctuation">)<span class="token comment">//这里不能使用逻辑值true,只能使用字符串true
<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Allow-Origin"<span class="token punctuation">, <span class="token variable">$request<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Origin"<span class="token punctuation">)<span class="token punctuation">)
<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Allow-Headers"<span class="token punctuation">, <span class="token variable">$request<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Request->Headers"<span class="token punctuation">)<span class="token punctuation">)
<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Request-Method"<span class="token punctuation">, <span class="token variable">$request<span class="token operator">-<span class="token operator">><span class="token function">header<span class="token punctuation">(<span class="token double-quoted-string string">"Access-Control-Request->Method"<span class="token punctuation">)<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</blockquote>
<p>设置的关键点是<code>Access-Control-Allow-Credentials</code>必须设置为<code>true</code>, 从而允许跨域请求时带上相关cookie。</p>
<ul>
<li>客户端代码配置,<br>
以jQuery.ajax为例:</li>
</ul>
<pre class="line-numberslanguage-javascript"><code class="javascriptlanguage-javascript">$<span class="token punctuation">.<span class="token function">ajax<span class="token punctuation">(<span class="token punctuation">{
headers<span class="token punctuation">:<span class="token punctuation">{
<span class="token string">"Content-Type"<span class="token punctuation">:<span class="token string">"text/plain"<span class="token punctuation">,
<span class="token punctuation">}<span class="token punctuation">,
url<span class="token punctuation">:url<span class="token punctuation">,
type<span class="token punctuation">:<span class="token string">"POST"<span class="token punctuation">,
data<span class="token punctuation">: bodyText<span class="token punctuation">,
dataType<span class="token punctuation">:<span class="token string">"json"<span class="token punctuation">,
xhrFields<span class="token punctuation">: <span class="token punctuation">{
withCredentials<span class="token punctuation">: <span class="token boolean">true
<span class="token punctuation">}<span class="token punctuation">,
<span class="token function-variable function">beforeSend<span class="token punctuation">: <span class="token keyword">function<span class="token punctuation">(<span class="token parameter">xhr<span class="token punctuation">) <span class="token punctuation">{
document<span class="token punctuation">.cookie <span class="token operator">= <span class="token string">"XDEBUG_SESSION=PHPSTORM;domain=localhost;path=/"<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">,
async<span class="token punctuation">:<span class="token boolean">false<span class="token punctuation">,
<span class="token comment">// 允许跨域
crossDomain<span class="token punctuation">: <span class="token boolean">true<span class="token punctuation">,
<span class="token function-variable function">success<span class="token punctuation">:<span class="token keyword">function<span class="token punctuation">(<span class="token parameter">res<span class="token punctuation">)<span class="token punctuation">{
<span class="token punctuation">}<span class="token punctuation">,
<span class="token function-variable function">error<span class="token punctuation">:<span class="token keyword">function<span class="token punctuation">(<span class="token parameter">err<span class="token punctuation">)<span class="token punctuation">{
<span class="token punctuation">}<span class="token punctuation">,
<span class="token function-variable function">complete<span class="token punctuation">:<span class="token keyword">function<span class="token punctuation">(<span class="token parameter">res<span class="token punctuation">)<span class="token punctuation">{
<span class="token punctuation">}<span class="token punctuation">,
<span class="token punctuation">}<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>设置的关键点是在<code>xhrFields</code>中增加<code>withCredentials:true</code>和在<code>beforeSend</code>函数中增加</p>
<pre class="line-numberslanguage-javascript"><code class="javascriptlanguage-javascript">document<span class="token punctuation">.cookie <span class="token operator">= <span class="token string">"XDEBUG_SESSION=PHPSTORM;domain=localhost;path=/"<span class="token punctuation">;
</span></span></span></span></code></pre>
<blockquote>
<p>说明一点:跨域请求开启调试,通过chrome书签或者直接修改浏览器cookie的方式并不起作用,猜测原因可能是因为浏览器本身的cookie和XmlHttpRequest中的cookie并不是一回事儿。</p>
</blockquote>
<ul>
<li>方式二</li>
</ul>
<blockquote>
<ul>
<li>借助nginx,开启跨域调试 <code>(大招来啦!)</code><br>
现在大部分Phper开发的环境都是LNMP,那么我们可以请nginx帮忙修改cookie,从而将cookie传输到php服务端。<br>
nginx默认不支持修改请求的header字段,我们需要下载安装<code>headers-more-nginx-module</code>扩展,下载地址 https://github.com/openresty/headers-more-nginx-module。<br>
PS:给nginx安装扩展不再赘述了哦。不会的话,自己百度下吧。</li>
<li>修改nginx.conf虚拟主机配置,如下所示:</li>
</ul>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">more_set_input_headers"Cookie:XDEBUG_SESSION=PHPSTORM; $http_cookie";
</code></pre>
</blockquote>
<p>其它操作同上,不再赘述。</p>
<h5>3)<strong>php脚本调试</strong></h5>
<p>有两种处理方式:</p>
<blockquote>
<ul>
<li>方式一:<br>
打开Phpstorm,找到myscript.php文件,点击右键<code>Debug 'myscript.php'</code>即可。</li>
<li>方式二:<br>
修改环境变量也可以开启Xdebug调试</li>
</ul>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">export XDEBUG_CONFIG="XDEBUG_SESSION=PHPSTORM"
php myscript.php
</code></pre>
</blockquote>
<h5>4)<strong>调试外网远程主机</strong></h5>
<p>分为如下几步:</p>
<blockquote>
<ul>
<li>
<p>设置内网穿透,用的是花生壳,我将花生壳分配的域名和端口指向我本机IP192.168.9.28和本机9001端口。</p>
<br>
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 687px">
<div class="image-view" data-width="896" data-height="687"><img src="https://upload-images.jianshu.io/upload_images/5394123-9bad199399910303.png?imageMogr2/auto-orient/strip|imageView2/2/w/896"></div>
</div>
<div class="image-caption">内网穿透端口映射.png</div>
</div>
</li>
</ul>
</blockquote>
<p>PS:如果觉得内网穿透麻烦的话,也可以使用ssh来实现同样的功能,而且是免费的。<br>
参见我写的另一篇文章利用ssh隧道,进行外网php xdebug调试和nodejs调试</p>
<blockquote>
<ul>
<li>修改远端主机php-fpm的php.ini的xdebug部分如下:</li>
</ul>
</blockquote>
<pre class="line-numberslanguage-ini"><code class="inilanguage-ini">
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
</code></pre>
<blockquote>
<ul>
<li>重启php-fpm</li>
</ul>
</blockquote>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">service php7.0-fpm restart
</code></pre>
<blockquote>
<ul>
<li>openresty或者nginx的server块中添加以下配置,开启xdebug session。</li>
</ul>
</blockquote>
<pre class="line-numberslanguage-shell"><code class="shelllanguage-shell">more_set_input_headers"Cookie:XDEBUG_SESSION=PHPSTORM; $http_cookie";
</code></pre>
<p>如果不愿意用openresty的方式,那么点击浏览器标签<code>start-debugger</code>也可开启xdebug session</p>
<blockquote>
<ul>
<li>
<p>本机IDE添加serverMapping映射</p>
<br>
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 294px">
<div class="image-view" data-width="1309" data-height="294"><img src="https://upload-images.jianshu.io/upload_images/5394123-0c2cf20fdfcf475c.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200"></div>
</div>
<div class="image-caption">serverMapping映射.png</div>
</div>
</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>
<p>新建一个运行调试php_webApplication的任务</p>
<br>
<div class="image-package">
<div class="image-container" style="max-width: 396px; max-height: 237px">
<div class="image-view" data-width="396" data-height="237"><img src="https://upload-images.jianshu.io/upload_images/5394123-34ea73896fe62514.png?imageMogr2/auto-orient/strip|imageView2/2/w/396"></div>
</div>
<div class="image-caption">image</div>
</div>
</li>
</ul>
</blockquote>
<div class="image-package">
<div class="image-container" style="max-width: 295px; max-height: 568px">
<div class="image-view" data-width="295" data-height="568"><img src="https://upload-images.jianshu.io/upload_images/5394123-c758bc8980afc181.png?imageMogr2/auto-orient/strip|imageView2/2/w/295"></div>
</div>
<div class="image-caption">新建php web application.png</div>
</div>
<blockquote>
<ul>
<li>最后一步,打上断点,点击菜单上<code>RUN</code>=><code>debug xxx web Application</code>,就可以开启调试了。</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>遗留问题:外网远程调试,必须点击菜单上的<code>RUN</code>=><code>debug xxx web Application</code>才能正常进行调试,其它方式打开网站的话,调试总是会出各种各样的问题。</li>
</ul>
</blockquote>
<hr>
<p>Xdebug开启调试的配置就这么简单。。。<br>
END!</p><br><br>
来源:https://www.cnblogs.com/ashaff/p/11609343.html
頁:
[1]