PHP の変数をトレースする HTTPTrace をちょっと改造してみた

  HTTPTrace とは、Windows アプリケーションと連動して PHP の変数の内容を表示するツールです。
  以下のページにて配布されています。

- 過去と他人はかえられないが、未来と自分はかえられる - [PHP]値を調べたい時に外部に出力するツール(var_dumpするよか便利)
  http://d.hatena.ne.jp/magiwo/20070821

  HTTPTrace は print_r() や var_dump() と異なり、ブラウザなどの画面ではなく Windows アプリケーションに変数の内容を表示するのが特長です。
  面白そうなので少し試してみました。

  まず、HTTPTraceServer.exe を起動して [Start] を選択します。このアプリケーションが PHP から変数の内容を受け取る HTTP サーバになっているようです。

  次にサンプルプログラムを動かします。

// HTTPTrace ライブラリ
require_once 'htrace.php';

// HTTPTraceServer.exe を実行しているマシンの設定
htrace_set('192.168.1.100', 6006);

// 変数の内容を送信
htrace($_SERVER);


  これをブラウザで実行すると HTTPTraceServer.exe は以下のように表示されます。

  

  使い方はいたって簡単ですが、いくつか気づいた点があったので改造してみました。

1. allow_call_time_pass_reference = Off のとき警告がでる。

  php,ini などで allow_call_time_pass_reference が Off (デフォルトは On) の場合は、以下のように警告が表示されます。

Warning: Call-time pass-by-reference has been deprecated

  ソースを見ると fsockopen() の 第 3, 4 引数をリファレンスで渡しているのが原因で、これはリファレンスで渡す必要がないので、修正しました。

// 修正前
$fp = fsockopen($host, $port, &$err_num, &$err_msg, 1);

// 修正後
$fp = fsockopen($host, $port, $err_num, $err_msg, 1);

2. HTTPTraceServer.exe が起動していないとき警告がでる。

  当たり前といえば、当たり前ですが若干気になったのでエラー制御演算子 (@) で警告が出ないようにしました。

// 修正前
$fp = fsockopen($host, $port, $err_num, $err_msg, 1);

// 修正後
$fp = @fsockopen($host, $port, $err_num, $err_msg, 1);

3. ソースファイルのパスが UNIX 環境でうまく区切れていない

  HTTPTraceServer.exe は htrace() されたソースファイルをツリー上に表示してくれて非常に便利なのですが、UNIX 環境ではうまく表示されません。例えば以下のようにツリーではなく一行で表示されます。

%2Fhome%2Fhttpd%2Fpocari%2FHTTPTrace-0.1.0%2Fsample.php

  Windows 環境を想定しているのかパスの分解が \ (バックスラッシュ) になっていたので、DIRECTORY_SEPARATOR (PHP4 >= 4.0.7, PHP 5) を使って、これを修正しました。

// 修正前
$exp = explode('\\', $debug['file']);

// 修正後
$exp = explode(DIRECTORY_SEPARATOR, $debug['file']);


  これで無事にソースがツリー上に表示されるようになりました。

4. 何かしらの定数で htrace() を実行しないようにしたい

  具体的には USE_HTRACE という定数を実装して、これが false の場合は htrace() が無効になるようにしました。

// 修正前
function htrace($vars, $stop=false)
{
    $trace = debug_backtrace();
    $debug = array_shift($trace);
    $exp = explode('\\', $debug['file']);
    $key = '';
    foreach ($exp as $num=>$dt) {
        $key .= rawurlencode($dt).'/';
    }
    $key .= sprintf("%05d", $debug['line']);
    $inc = new HTTPTraceClient();
    $inc->ModeGlobal();
    $inc->SendValue($key, $vars, $stop);
}

function htrace_set($ip='localhost', $port=6006)
{
    $inc = new HTTPTraceClient();
    $inc->ModeGlobal(array('ip'=>$ip, 'port'=>$port));
}

// 修正後
if (!defined('USE_HTRACE')) {
    define('USE_HTRACE', true);
}

if (USE_HTRACE) {
    function htrace($vars, $stop=false)
    {
        $trace = debug_backtrace();
        $debug = array_shift($trace);
        $exp = explode(DIRECTORY_SEPARATOR, $debug['file']);
        $key = '';
        foreach ($exp as $num=>$dt) {
            $key .= rawurlencode($dt).'/';
        }
        $key .= sprintf("%05d", $debug['line']);
        $inc = new HTTPTraceClient();
        $inc->ModeGlobal();
        $inc->SendValue($key, $vars, $stop);
    }

    function htrace_set($ip='localhost', $port=6006)
    {
        $inc = new HTTPTraceClient();
        $inc->ModeGlobal(array('ip'=>$ip, 'port'=>$port));
    }
} else {
    function htrace() {}
    function htrace_set() {}
}


  これを利用することで、htrace.php を require/include する前に USE_HTRACE を false に設定すれば htrace() は何もしなくなって便利です。

// htrace を無効にする
define('USE_HTRACE', false);

require_once 'htrace.php';
htrace_set('192.168.1.100', 6006);

// なにもしない
htrace($_SERVER);


  以上のパッチを以下においておきます。

- HTTPTrace-0.1.0.diff
  http://pocari.org/tools/HTTPTrace/HTTPTrace-0.1.0.diff

  このような PHP のデバッグツールは大変ありがたいです。使いどころによっては大変威力を発揮するツールだと思います。

- 追記 (2007-08-31)
  上記パッチを適用していただきました。ありがとうございます。
  http://d.hatena.ne.jp/magiwo/20070830