1. 程式人生 > >PHP Xdebug除錯專題

PHP Xdebug除錯專題

1、介紹與安裝

Xdebug是一個PHP擴充套件,安裝配置好後,可以自動記錄運行了哪些函式,用了多少毫秒,從哪個檔案執行到哪個檔案等等

它記下來的除錯資訊很詳細,對一些複雜程式跟蹤除錯有很大的輔助效果,能明顯快速地定位問題,縮短除錯時間

官方網站:http://xdebug.org/

官方文件:http://xdebug.org/docs/all_settings


先確認一下你有沒有安裝Xdebug

執行phpinfo();如果沒有圖中這一塊內容就是沒有安裝Xdebug了

安裝方法

並不是隨便下載擴充套件檔案安裝就可以的,它針對不同版本的PHP有不同的擴充套件檔案提供給你下載

下面教你通過官方的分析結果來引導你安裝

  1. 先進入官方網站,然後點選上面橫向導航中的download

  2. 進入下載頁面後,雖然頁面下面有很多版本的下載,如果你不熟悉的話我不建議你下載,沒準安裝是不能用的,按我接下來說的去安裝一般都能妥妥地使用起來

    點選custom installation instructions連結進入自定義安裝引導頁面

  3. 進入自定義安裝引導後是下面這樣的:

    分析需要一段時間,我最短等過幾秒的,最長等過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的返回值,並且大家細心的話一定能發現它們