1、介紹與安裝
Xdebug是一個PHP擴展,安裝配置好后,可以自動記錄運行了哪些函數,用了多少毫秒,從哪個文件運行到哪個文件等等
它記下來的調試信息很詳細,對一些復雜程序跟蹤調試有很大的輔助效果,能明顯快速地定位問題,縮短調試時間
官方網站:http://xdebug.org/
官方文檔:http://xdebug.org/docs/all_settings
先確認一下你有沒有安裝Xdebug
執行phpinfo();
如果沒有圖中這一塊內容就是沒有安裝Xdebug了
安裝方法
並不是隨便下載擴展文件安裝就可以的,它針對不同版本的PHP有不同的擴展文件提供給你下載
下面教你通過官方的分析結果來引導你安裝
-
先進入官方網站,然后點擊上面橫向導航中的download
-
進入下載頁面后,雖然頁面下面有很多版本的下載,如果你不熟悉的話我不建議你下載,沒准安裝是不能用的,按我接下來說的去安裝一般都能妥妥地使用起來
點擊custom installation instructions鏈接進入自定義安裝引導頁面
-
進入自定義安裝引導后是下面這樣的:
分析需要一段時間,我最短等過幾秒的,最長等過60秒左右,有時候也看網絡情況吧,畢竟是提交到國外網站,分析完成后會自動顯示分析結果,如下圖:
另外如果在linux系統環境下執行phpinfo也可以這樣的,只是安裝流程會比較多,引導你敲各種命令神馬的
2、記錄運行軌跡
先設置以下兩項配置
#開啟自動跟蹤回溯 xdebug.auto_trace=on #設置回溯信息輸出目錄 xdebug.trace_output_dir="E:\xdebug"
然后通過瀏覽器訪問任何一個http入口腳本,腳本內容可以復制我下面的演示代碼:
$str = 'abc'; $str1 = substr($str, 0, 2); function xx($a, $b){ $x = array(); array_push($x, $a); array_push($x, $b); yy(); return $x; } function yy(){ print_r(123); }
運行后就會在回溯信息輸出目錄下產生類似這樣的一個文件
而打開它文件內容則是這樣的:
內容中每一行都顯示了在哪個文件的哪一行執行了哪個函數,其中你注意一下第1次出現的array_push
函數相對於上一行的xx
函數縮進了的,這意思是說array_push函數是在xx函數里面執行的
換成運行你自己的項目代碼,相信就能看到成千上萬行回溯代碼了,包括調用了哪個對象的哪個方法也是這么看
這個回溯追蹤的好處是你如果平時發現頁面突然變空白了,怎么輸出東西都看不見,於是只要通過這個回溯追蹤調試,看看輸出信息文件的最后幾行調用的函數和文件行號你就大概知道出錯位置在哪里了
最后提醒:它只記錄有函數執行的地方,沒有函數執行的地方是不會語錄的,比如echo,include,isset等語句是不會記錄的,於是你也能從中確認哪些是函數,哪些是語句了
3、設置文件名
默認情況下生成的文件名是類似trace.150145005.xt
的,我個人覺得這樣命名並不友好,起碼就算你重復運行其它腳本都是將調試信息記錄到這個文件中的,如果想為每個不同的腳本做不同的記錄就要先復制備份開,再運行讓它產生新的同名文件了
所以我們要通過xdebug.trace_output_name
配置項來設置調試信息的文件名
樣本配置:
xdebug.auto_trace=on xdebug.trace_output_dir="E:\xdebug" xdebug.collect_params=0 #重點是下面這個,值為%R表示以請求地址來命名,這樣不同地址就會有不同的調試信息文件 xdebug.trace_output_name="%R"
然后訪問http://xxx.com/a.php
就會產生_a_php.xt
這個文件
而且同一個入口地址不同參數都會不同喔,你試試訪問http://xxx.com/a.php?x=y
就會產生_a_php_x=y.xt
這個文件
下面我列出所有命名參數
參數 | 含義 | 例子 | 命名結果 |
---|---|---|---|
%c | 以URL中文件目錄的CRC32運算結果命名 | trace.%c | trace.1258863198.xt |
%p | 以進程PID命名 | trace.%p | trace.5174.xt |
%r | 以隨機數命名 | trace.%r | trace.072db0.xt |
%s | 入口腳本名稱,實際上我測試結果是不會生成文檔,原因暫時不明 | cachegrind.out.%s | cachegrind.out._home_httpd_html_test_xdebug_test_php |
%t | 以時間戳命名 | trace.%t | trace.1179434742.xt |
%u | 以毫秒級時間戳命名 | trace.%u | trace.1179434749_642382.xt |
%H | 以$_SERVER['HTTP_HOST']這個域名命名 | trace.%H | trace.kossu.xt |
%R | 以$_SERVER['REQUEST_URI']這個URI部分命名 | trace.%R | trace._test_xdebug_test_php_var=1_var2=2.xt |
%U | 以$_SERVER['UNIQUE_ID']這個唯一的請求ID來命名 | trace.%U | trace.TRX4n38AAAEAAB9gBFkAAAAB.xt |
%S | 以session_id命名,但前提是cookie中有PHPSESSIONID | trace.%S | trace.c70c1ec2375af58f74b390bbdd2a679d.xt |
%% | 以兩個百分號命名,我看不懂加這個命名方式有何意義,求教大神啊! | trace.%% | trace.%%.xt |
4、記錄函數參數
有時候你即使有了回溯也看不出"為什么程序會這樣調用,怎么計算進來的"
於是可以嘗試開啟函數參數記錄來看看每一次調用函數時,傳給那些函數的參數都是什么,那么結果能進一步明了
-
復制如下配置
xdebug.auto_trace=on xdebug.trace_output_dir="E:\xdebug" #通過設置collect_params選項值為3開啟參數記錄 xdebug.collect_params=3
於是跑一趟代碼下來,調試信息文件內容就是這樣的,看到了吧,函數的括號里多了參數,而沒有開啟collect_params時函數后面只有一個空括號的
5、手動觸發記錄
請求參數觸發
如果配置xdebug.auto_trace=on
的話,你運行任何PHP文件都會產生回溯記錄
但有時候你只需要回溯某一個地址的運行軌跡,可以通過設置xdebug.trace_enable_trigger=on
來實現,但前提是要設置xdebug.auto_trace=off
(或者刪除這個選項))
配置樣本:
xdebug.auto_trace=off xdebug.trace_enable_trigger=on xdebug.trace_output_dir="E:\xdebug"
這樣你訪問/index.php
不會產生回溯記錄,但是你如果修改一下URL參數,加上XDEBUG_TRACE
這個參數名,不用參數值,只要有參數名就行了
就是訪問這樣的/index.php?XDEBUG_TRACE
地址,然后就會產生文件了,這就是通過GET參數觸發
而通過POST請求也是這樣,如果你的POST參數中帶有XDEBUG_TRACE才會有回溯
$.ajax({
url : '/index.php', type : 'post', data : { a : 1, XDEBUG_TRACE : 11 //這個值隨便設置,如果你不設置就不會POST這個字段上去! } });
函數觸發
在測試前請先確認配置xdebug.auto_trace=off
(關閉自動回溯)
然后找到你要開始追蹤回溯的代碼位置調用xdebug_start_trace
函數,再在要停止追蹤回溯的位置調用xdebug_stop_trace
函數,這樣就會生成回溯信息,並且是對你開始和結束trace函數之間的代碼進行記錄,其它無關的代碼是不記錄的
樣例代碼:
$str = 'abc'; $str1 = substr($str, 0, 2); xx('a', 'b'); function xx($a, $b){ xdebug_start_trace(); //開始記錄回溯 $x = array(); array_push($x, $a); print(222); array_push($x, $b); xdebug_stop_trace(); //結束記錄回溯 yy(); return $x; } function yy(){ print_r(123); }
並且要注意,通過函數觸發的話並不需要什么配置,你只要開啟了擴展就可以,就是只保留zend_extension="xdebug.dll"
就可以,其它xdebug的相關配置可以完全不配置,如果有文件名定制需求就再保留xdebug.trace_output_name
選項就足夠了
然而如果你開啟了xdebug.auto_trace
其實相當於讓PHP啟動時就自動執行xdebug_start_trace函數,於是會報錯說這個函數已經執行過了,所以為避免麻煩請不要開啟xdebug_start_trace
這個調試更加精准,因為如果整個運行周期都回溯下來,起碼有成千上萬行,查找成為了艱難的事情
而函數觸發時就縮小了你需要的范圍,查找就快捷了很多!
6、記錄返回值
記錄了函數參數還不足夠,想要記錄每一次函數的返回值也可以,設置xdebug.collect_return=on
以下是我的演示代碼:
$str = 'abc'; $str1 = substr($str, 0, 2); xx('a', 'b'); function xx($a, $b){ $x = array(); array_push($x, $a); print(222); array_push($x, $b); yy(); return $x; } function yy(){ print_r(123); }
運行后所得出的調試信息如下
其中>=>
符號后面的值就是相關函數的返回值,然而並不是每一次>=>
的值都是上一行調用的返回值,至於它是屬於誰的返回值,還要看我紅色線所連接的行
比如>=> array (0 => 'a', 1 => 'b')
則表示-> xx('a', 'b') E:\test\index.php:4
的返回值,並且大家細心的話一定能發現它們的縮進是一樣的