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

GPolygon.fromEncoded() を利用して Google Maps のポリゴン表示を軽量化する

  Google Maps では GPolygon を利用してポリゴン (多角形) を描画することができます。
  しかし、GPolygon を使ったポリゴン描画には重大な欠点がありました。
  それは、点の数を多くすると Opera や Safari では描画ができずに、ブラウザが固まってしまう場合があるというものです。

  それを解決する手段かどうかはわかりませんが、Google Maps API v2.78 から GPolygon.fromEncoded() というメソッドが追加されて、あらかじめポリゴンのデータをエンコードしたデータを指定することができるようになりました。

- Official Google Maps API Blog: v2.78: Go ahead, Scroll your mouse wheels & encode your polygons!
http://googlemapsapi.blogspot.com/2007/04/v278-go-ahead-scroll-your-mouse- ...

  そこで、サンプルを作って実際にテストしてみました。

  以下サンプルでは、500 個の点 (座標値) を用いています。
  また、サンプルで利用したデータは、An encoding utility for polyline and polygon data から拝借しています。

1. GPolygon.fromEncoded() を利用しない場合

  http://pocari.org/demo/gpolygon/gpolygon.html

  (こちらのサンプルは、Opera、Safari の場合、ブラウザが固まってしまう場合があるのでご注意ください)

  こちらは配列に入っている座標を GPoint に追加して、最後に GPolygon で描画しています。

// 座標の配列 (実際は 500 個) を用意して
var mapPoints = [
    [ -78.57945,  33.88215 ],
    [ -78.65546,  33.94883 ],
    [ -79.07426,  34.304726 ],
       :
    [ -78.65546,  33.94883 ],
    [ -78.57945,  33.88215 ]
];

// GPoint の配列を作成して
var points = [];
for (var i = 0, len = mapPoints.length; i < len; ++i) {
    points.push(new GPoint(mapPoints[i][0], mapPoints[i][1]));
}

// 描画する (map は GMap2 のオブジェクト)
map.addOverlay(new GPolygon(
    points,    // 座標値
    '#3366cc', // 線の色
    2,         // 線の太さ
    1.0,       // 不透明度
    '#e5ecf9', // 塗りつぶす色
    0.5        // 塗りつぶす色の不透明度
));


  前述のように Opera、Safari の場合、ブラウザが固まってしまう場合があります。

2. GPolygon.fromEncoded() を利用する場合

  http://pocari.org/demo/gpolygon/gpolygon-fromencoded.html

  こちらは、あらかじめエンコードした座標値を GPolygon.fromEncoded() で描画しています。

// エンコードされた座標値 (途中で省略)
var encodedPoints = 'mrxmEppr~Mw_LbzMi...';
// エンコードされたズームレベル値 (途中で省略)
var encodedLevels = 'PFFHHMGEHCMLEGLLJ...';

// 描画する (map は GMap2 のオブジェクト)
map.addOverlay(new GPolygon.fromEncoded({
    polylines: [{
        points:     encodedPoints, // エンコードされた座標値
        levels:     encodedLevels, // エンコードされたズームレベル値
        color:      '#3366cc',     // 線の色
        opacity:    1.0,           // 線の不透明度
        weight:     2,             // 線の太さ
        numLevels:  18,            // ズームレベルの分割数
        zoomFactor: 2              // ?
    }],
    fill:    true,      // 領域を塗りつぶすかどうか
    color:   '#e5ecf9', // 塗りつぶす色
    opacity: 0.5,       // 塗りつぶす色の不透明度
    outline: true       // 線を表示するかどうか
}));


  こちらを利用することで、Opera、Safari でもブラウザが固まることはなくなります。

  さて、肝心の座標値をエンコードする方法ですが、アルゴリズムが公開されています。

- Google Maps API Documentation - Encoded Polyline Algorithm
  http://www.google.com/apis/maps/documentation/polylinealgorithm.html

  さらには、エンコードユーティリティもあります。

- Google Maps API Documentation - Polyline Encoding Utility
  http://www.google.com/apis/maps/documentation/polylineutility.html

  しかし、このユーティリティは使いづらいので、以下のサイトがお勧めです。

- An encoding utility for polyline and polygon data
  http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/encodeForm.htm ...

  とても便利な GPolygon.fromEncoded() ですが、zoomFactor といういまいちよくわからないパラメータが出てきます。
  とりあえず、適当に 2 とかしていますが、これが妥当かどうかはわかりません (期待通りに描画はされてはいます)。

  このあたりの参考になる 2 つのエントリを紹介しておきます (GPolygon ではなくて GPolyline ですが参考になります)。

- GPolyline.fromEncoded (hPod)
  http://hwat.sakura.ne.jp/hpod/200609/14-200000/

- Encoded Polyline (hPod)
  http://hwat.sakura.ne.jp/hpod/200610/17-200000/

  なにはともあれ、GPolygon.fromEncoded() で Opera や Safari でも問題なくポリゴンが描画できるようになりますので、同様の問題を抱えている方は試してみてはいかがでしょうか。

FeedBurner のマイ・ブランドを VALUE DOMAIN で利用する

  FeedBurner のマイ・ブランドとは FeedBurner で提供されている RSS Feeds などを自分のドメインで運用できるようにしたものです。
  以前は PRO 機能として有料でしたが、Google が買収したことで無料になったと思われます。

  設定は、以下の説明ページにあるものそのままです。

- Feedburner Infomation | マイブランド設定例
  http://www.feedburner.info/?eid=9789

  以下、マイ・ブランドで使用するドメインを feeds.pocari.org とします。

1. CNAME を設定する

  DNS の設定で、cname feeds feeds.feedburner.jp. を設定します。
  CNAME
  feeds.feedburner.jp. の末尾の . を忘れずにつけます。

2. CNAME の確認

  nslookup なり dig なりで feeds.pocari.org が引けるのを確認します。

$ dig feeds.pocari.org

; <<>> DiG 9.3.4 <<>> feeds.pocari.org
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 243
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;feeds.pocari.org.              IN      A

;; ANSWER SECTION:
feeds.pocari.org.       103     IN      CNAME   feeds.feedburner.jp.
feeds.feedburner.jp.    276     IN      A       66.150.96.120

;; Query time: 9 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Mon Aug 20 13:45:25 2007
;; MSG SIZE  rcvd: 83

3. FeedBurner で設定する

  これは、上記説明ページに書いてあるとおりです。
  [マイアカウント] - [マイ・ブランド] に feeds.pocari.org を設定します。

4. 確認

  http://feeds.feedburner.jp/clpocariorg で提供していた RSS Feeds が
  http://feeds.pocari.org/clpocariorg で提供できることを確認します。

  ということで、本サイトの RSS Feeds の URL は、

  http://feeds.pocari.org/clpocariorg

  に変更しました。.htaccess でリダイレクトを行なうようにしているので RSS リーダなどの設定を変更する必要はありません。
  これまでどおり http://cl.pocari.org/cl.rdf にアクセスしていただければと思います。

zsh でログイン時に screen を起動する方法

  ~/.zlogin に以下を記述する。

if [ ! "$WINDOW" ]; then
    exec screen -S main -xRR
fi


  ログイン直後にいつも screen を打っていたのですが、これで楽になりました。

- 追記 (2007-08-21)
  コメント欄で情報をいただいたように、他のホストにログインすると screen が二重起動する件ですが、以下のようにして対処できそうです。

if [ $TERM != "screen" ]; then
    exec screen -S main -xRR
fi


  ただし、Solaris の場合は terminfo に screen の記述がないので上記設定ではうまくいきません。

  結局メインで使うマシンのみに、一番上の設定をしてそれ以外のマシンは手動で screen を打つという運用でカバーすることにしました。