|
[2005/12/31]Xdebug2.0.0beta5がリリースされています。PECLのページからどうぞ。
PHPでちょっとした規模の開発を行っていると当然ユーザー定義関数やクラスが増えてきて、だんだんでバッグがしにくくなります。構文エラーとかは問題ないのですが、例えば何らかのDBアクセスクラスを使ってSQL文を実行してエラーが発生したとき、PHPが表示してくれるエラー発生行番号はあくまでDBアクセスクラスの行番号になってしまいます。また、条件によってSQLを組み変える場合など、最終的にどの様なSQLを実行したのか
<?php echo $sql; ?>
などとして表示させないと分からなかったりします。
PHP4.3.xならdebug_backtraceとtrigger_errorで実装できるだろうということは分かっているのですが、PHP本体でどうにかならないかなぁ。。。と思って調べてみると、丁度良いものがありました。
XdebugはPHP拡張モジュールとして配布されており、2004/11/11時点の最新版は1.3.2(安定版)と2.0.0beta1です。今回は1.3.2を使用しました。また、Xdebugは機能的にも豊富で、以下の機能が用意されています。
- 従来のエラーメッセージと共に関数のスタックや各パラメータ(GET/POST/COOKIE/SESSION/SERVER/...)を表示
- 無限ループからの保護
- リモートデバッグ
- プロファイリング
- コードカバレッジ(code coverage)
今回はXdebugの導入とStackTraceを中心な内容ですが、他の機能についても追って追記していきたいと思います。個人的にはコードカバレッジに非常に興味があります。。。
[2005/04/24] PHP5でのコードカバレッジについては、PHPUnit2についてのページにもちょっとだけまとめてあります。
さて、インストール方法は他のPHP拡張モジュールと同様以下の手順になります。
●Xdebugのインストール$ tar zxf xdebug-1.3.2.gz
$ cd xdebug-1.3.2/
$ phpize
$ ./configure --enable-xdebug
$ make
$ su -
# make install
# vi /path/to/php.ini
#
php.iniですが、以下の行をphp.iniの最後に追加しました。ただし、extension_dirを設定していない場合、正しく設定し以下の行を追加するか、xdebug.soへの絶対パスを記述します。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; for Xdebug
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
extension="xdebug.so"
ここまでできたら、Apacheの再起動を行い、phpinfoで確認します。以下のような内容が表示されているはずです。
無事インストールできたら、早速動かないスクリプト(?)で確認してみましょう。今回は。。。うーむ。サンプルの手持ちがない。。。ということで、JDBC風Oracleアクセスクラスを手直ししたものと以下のスクリプトで試してみます。なお、サンプル一式はwww.doyouphp.jpからダウンロードできます。
●oci_test_xdebug.php
<?php
require_once "jp/ne/hi_ho/pat/sql/jdbc/OCI.phl";
?>
<?php
$dbc =& new OCI();
if (!$dbc->connect("scott", "tiger", "orcl")) {
die("接続に失敗しました<br>");
}
$sql = "SELECT empno FROM emp WHERE empno LIKE ? || '%' ";
$pstmt = $dbc->prepareStatement($sql);
if ($dbc->isError($pstmt)) {
echo "Error at prepareStatement()<br>";
echo $pstmt->getMessage() . "<br>";
echo $pstmt->getCode() . "<br>";
exit;
}
$ret = $pstmt->setString(1, $_GET['id']);
if ($dbc->isError($ret)) {
echo "Error at setString()<br>";
echo $ret->getMessage() . "<br>";
echo $ret->getCode() . "<br>";
exit;
}
$rset = $pstmt->executeQuery();
if ($dbc->isError($rset)) {
echo "Error at executeQuery()<br>";
echo $rset->getMessage() . "<br>";
echo $rset->getCode() . "<br>";
$pstmt->close();
exit;
}
while ($rset->next()) {
echo "no=" . $rset->getString("EMPNO") . "\t";
echo "name=" . $rset->getString("ename") . "<br>";
}
$rset->close();
$pstmt->close();
$dbc->close();
?>
このサンプル、一見まともそうなんですが、実行すると$rset->getString("ename")の部分でNoticeが発生します。原因はSELECT文でカラムを指定していないためなのですが、意外と分かりにくいバグです。
まず、Xdebugなしでは以下のように出力されます。前述の通り、メッセージがアクセスクラス側のエラーのように出力されてしまうため、実際どの行でNoticeが発生しているのか分かりません。
一方、Xdebugありの場合は以下のように出力されます。スタックトレースが表示されるため、oci_test_xdebug.phpの38行目であることがすぐに分かります(画像がちょっと見づらいかも知れませんね。。。)。
ついでにGETパラメータが正しく渡ってきているかどうかも表示するようにしちゃいましょう。方法は至って簡単で、php.iniに以下の行を追加するだけです。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; for Xdebug
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
extension="xdebug.so"
xdebug.dump.GET=*
この場合、エラー発生時に全てのGETパラメータをダンプするようになります。また、「*」の部分はカンマ区切りでパラメータ名を指定する事もできます。なお、POST/COOKIE/SESSION/SERVER/ENV/REQUEST/FILESについても同様ですので、必要なものをphp.iniに追記しておくと良いと思います。
実際、これだけでもデバッグ効率はかなり上がると思います。
[2005/04/27追記] PHP4.3.11+Xdebug2.0.0beta2の組み合わせにしたところ、以下のようにメソッド・関数の引数まで表示されるようになっていました。これは便利!
あ。上のイメージはxdebug.cをちょっといじって色を変えてあります。というか、2.0.0beta2の色具合が何とも。。。個人的にはあまり好きでないですね。オリジナルの色は、みなさんがインストールして確認してみてください(^-^;
また、コードカバレッジ関数(debug_xxx_code_coverage())も動作するようになっていました。いい感じです。もう一つ。Xdebugって、PECLに登録されていたんですね。。。最近知りました(^-^;
|