XdebugまたはPHP Debuggerでデバッグする: 手動でもAIとでも
JumPHP IDEには本格的なステップデバッガーがあります。プログラムを任意の行で止め、変数を確認し、1つを書き換えて、1ステップずつ進められます。XdebugのプロトコルであるDBGpを話すので、2つのエンジンを操作できます。
- Xdebug: 従来からのエンジン(デフォルト)。
- PHP Debugger: 新しいDBGpデバッガー。無料のオープンソースで、Xdebugの設定と互換性があり、オーバーヘッドはほぼゼロです。
IDEでは、どちらも同じように動きます。デバッガーをAI(Claude Code)に任せることもできます。AIがブレークポイントを設定し、プログラムを実行し、変数を読み、バグを自分で見つけます。
どちらのエンジンを選ぶか
| Xdebug | PHP Debugger | |
|---|---|---|
| JumPHPでは | デフォルト、すべてのランタイム | デスクトップランタイム(PHP 8.2〜8.5) |
| オーバーヘッド | PHPが目に見えて遅くなる | "near-zero overhead when idle"。常時有効で、設定するトリガーはなし |
asyncランタイム(PHP 8.6、runtime: async) |
対応 | 非対応: 代わりにXdebugが使われ、IDEがそれを知らせます |
| AI | JumPHPのMCPサーバー(bin/jumphp debug) |
専用のMCPサーバー(dbgp mcp)。スクリプトの出力やPHPの警告も見える |
実際には、日常のデバッグ、長時間の実行(600フレーム遊ぶゲーム、テストスイート)、AIによるデバッグにはPHP Debuggerを選びましょう。asyncランタイム(スレッド)で作業する場合や、Xdebugにしかできないことが必要な場合はXdebugのままにします。IDEでは両者を入れ替えられるので、同じプロジェクトで両方試せます。
PHP Debugger自身のページにはベンチマークの数値はなく、デバッグするまでコストはほぼゼロとだけ述べられています。差が気になる場合は、自分のプロジェクトで測定してください。
IDEでエンジンを選ぶ
- ヘッダーのデバッグボタン(実行の隣の虫のアイコン、
Shift+F9)でメニューが開きます: 次でデバッグ(今回の実行にXdebugかPHP Debuggerのどちらを使うか)と 既定のエンジン(以後、通常のクリックで使うエンジン)。ボタンを右クリックしても同じメニューが開きます。 - あるエンジンでの初回実行ではDockerイメージが1回ビルドされます(1分ほど)。2回目以降はすぐに始まります。
- プログラムがデバッガーに接続しなかった場合(先に終了した、または3分たっても何も起きない)は、通知でお知らせします。理由は「実行」ウィンドウの出力に出ていることがほとんどです。
ターミナルからエンジンを選ぶ
いつもどおり、すべてbin/jumphpを通します。
# Xdebug (default)
JUMPHP_XDEBUG=9003 bin/jumphp test pong
# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
JUMPHP_XDEBUG=<port>でステップデバッグが有効になります。PHPは、お使いのコンピューターのそのポートで待ち受けているデバッガーに接続します(composer、phpstan、php -lはこれなしで動きます)。JUMPHP_DEBUGGER=xdebug|php-debuggerでエンジンを選びます(デフォルトはxdebug)。php-debuggerの場合、bin/jumphpはデスクトップイメージをもとにイメージdocker/desktop-phpdebuggerを1回ビルドします。デスクトップイメージ自体には手が加わりません。- asyncランタイム(PHP 8.6)では「PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used」というメッセージが表示され、Xdebugが動きます。
IDEで手動デバッグする
- ブレークポイント: PHPの行の左にあるガターをクリックします。右クリックで条件(PHPの式。真のときだけ止まります。例:
$this->score < 0)を設定できます。Ctrl+F8でカーソル位置に設定します。ブレークポイントはプロジェクトごとに保存され、編集しても行に追従します。 - デバッグ(
Shift+F9): プログラムが動き、最初のブレークポイントで止まります。行がマークされ、Debugツールウィンドウが開きます。 - 確認する: コールスタック(フレームをクリックするとその変数が見えます)、必要に応じて読み込まれるツリー形式の変数、watches、止まった場所で任意のPHPの式を評価する入力欄。
- 値を変更する: 変数をダブルクリックするか
F2を押し、PHPの式(9、"Ada"、[1, 2]、null)を入力して、新しい値のまま続行します。 - 進める: 再開
F9、ステップオーバーF8、ステップインF7、ステップアウトShift+F8、カーソル位置まで実行Alt+F9、停止。 - 例外: 例外で停止…(Debugウィンドウの警告アイコン):
*またはクラス名(TypeError、App\GameOver)。例外がキャッチされるかどうかにかかわらず、スローされた場所で止まり、どの例外かをメッセージとともに表示します。
ホバーインスペクター (次のIDEアップデートで追加予定): プログラムがブレークポイントで止まっているとき、エディターで変数にマウスを重ねると、値の展開できるツリーが表示され、CopyとEditが使えます。
ゲームのヒント: ヘッドレス実行(test、shot)でデバッグしましょう。ウィンドウの中で止まったゲームは、再開するまでフリーズします。
AIとデバッグする
AIはvar_dump()よりもデバッガーを使うほうがうまくデバッグできます。実際の値を、1回に1つの問いで読み、コードには何も手を加えません。MCPサーバーは2つあります。同時に使うのはどちらか1つです(どちらもポート9003で待ち受けます)。
1. JumPHPのサーバー: bin/jumphp debug
IDE自身のデバッガーをMCPサーバーとして使います(Docker上で、Xdebugで動作します)。
claude mcp add jumphp-debug -- bin/jumphp debug
ツール:
| ツール | 内容 |
|---|---|
debug_breakpoints |
ファイルのブレークポイントを設定(lines、または{line, condition})。パスなしで一覧表示、clear_all |
debug_exceptions |
プログラムを止める例外(* = すべて、[] = なし) |
debug_wait |
プログラムがブレークポイントまたは例外で止まるまで待ち、場所、スタック、変数を返す |
debug_state |
止まっている場所、スタック、フレームの変数 |
debug_step |
step_over、step_into、step_out、run、stop: 次に止まるまで待つ |
debug_run_to |
指定した行まで実行 |
debug_eval |
止まっている場所でPHPの式を評価 |
debug_variables |
フレームの変数、またはその子要素($this->player、$list[3]) |
debug_set_value |
変数に新しい値(PHPの式)を設定 |
パスはプロジェクトからの相対パスです。ClaudeはJUMPHP_XDEBUG=9003を付けて、プログラムを自分でバックグラウンド起動し、そのあとdebug_waitを呼びます。
2. PHP Debuggerのサーバー: dbgp mcp
PHP Debuggerは、小さなプログラムdbgpに独自のMCPサーバーを同梱しています(MITライセンス。LinuxとmacOSはamd64とarm64、Windowsはamd64)。
# install (macOS / Linux)
curl -fsSL https://github.com/php-debugger/dbgp-client/releases/latest/download/install.sh | sh
dbgp -version
# for this project / for all your projects
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp
Claude Code内で/mcpを実行すると、接続されていることが確認できます。ツールはPHP Debuggerのドキュメントでの名前で次のとおりです。
- 接続:
status、listen、unlisten、sessions、wait_for_session、detach - ブレークポイント:
add_breakpoint、remove_breakpoint、breakpoints - 実行:
continue、wait_for_stop、stop - 確認:
stack、variables、variable、variable_value、source、output、warnings - 操作:
eval、set_variable - Docker / リモート:
add_path_mapping、path_mappings
便利なフラグ(すべて見るにはdbgp mcp -h): -php-port PORT(PHPが接続するポート、デフォルトは9003)、-mcp-port PORT、-idekey KEY、-map LOCAL=REMOTE(パスのマッピング、複数指定可)、そしてeval、set_variable、条件付きブレークポイントを禁止する-no-eval。この場合AIは見ることしかできません。ただし値は隠されないので、パスワードやキーはAIから見えたままです。
bin/jumphp経由では、JUMPHP_DEBUGGER=php-debugger bin/jumphp debugがdbgp mcpを起動します(コンピューターにdbgpのインストールが必要です)。そのあと、同じエンジンでプログラムを起動します。
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
セッションの実例
あなたからClaude Codeへ:
ゲーム
pongで、ボールが左のパドルを通り過ぎると、スコアが1ではなく2増えます。var_dumpではなくデバッガーを使ってください。 スコアが増える場所(PlaySceneを見てください)にブレークポイントを設定し、JUMPHP_XDEBUG=9003を付けてbin/jumphp test pongを実行し、そこで止めて、変数を読んで、理由を教えてください。原因を私に見せてから修正してください。
AIは上のツールを使って次のように進めます。
- 点を加える行を見つけ、その行が毎フレーム実行されるなら条件(
$this->ballX < 0)付きでブレークポイントを設定する。 - テストをバックグラウンドで起動し、停止を待つ(
debug_wait/wait_for_stop)。 $this->score、$this->scored、スタックを読み、この行を誰が呼んだかを確かめる。- 一度ステップアウトして(
debug_stepのstep_out)2つ目の呼び出し元を確認する。点が二重に数えられている。 - 何も編集せずに仮説を確かめる。
$this->scoredに値を設定し(debug_set_value/set_variable)、続行してスコアが正しいままか見る。 - そのあとで初めてコードを編集し、ブレークポイントなしでテストを再実行する。
ヒント
- はっきり伝える: 「デバッガーを使って」。そうしないと、エージェントはよく
var_dump()に戻ってしまいます。 - バグを再現するコマンド、期待する結果、疑わしい場所を伝えましょう。
- 小さなステップで:
step_overを数回、そして確認。600フレームをステップ実行するより、条件付きブレークポイント($enemy->hp <= 0)のほうが優れています。 - 変数を読ませ、式を評価させましょう。
var_dump()もechoも不要で、あと片付けもありません。 - ウィンドウよりヘッドレス実行(
test、shot、php)を選びましょう。 - 機密情報: AIは読んだ変数をすべて見ます(パスワード、トークン、APIキー)。テストデータでデバッグし、プログラム内でコードを実行させたくない場合は
dbgpに-no-evalを付けてください。 - デバッグしないプロジェクトに、デバッガーのMCPサーバーを接続したままにしないでください。
claude mcp removeで削除します。
トラブルシューティング
何も止まらない / "did not connect"。
ポートでデバッガーが待ち受けていますか(IDEのDebugウィンドウ、またはMCPサーバー)? プログラムはJUMPHP_XDEBUG=<port>を付けて、待ち受け側と同じエンジンで起動する必要があります。
ポートがすでに使用中。
9003で2つが待ち受けています。IDEとbin/jumphp debug(またはdbgp mcp)、あるいは2つのIDEです。どちらかを止めるか、別のポートを使ってください。JUMPHP_XDEBUG=9010とJUMPHP_DEBUG_PORT=9010 bin/jumphp debug、またはdbgp -php-port 9010 mcp。
ブレークポイントに到達しない。
コードのない行(コメント、空行、閉じ括弧)にあるか、プログラムが一度も読み込まないファイルにあります。debug_stateを実行する、またはスタックを見て現在位置を確認してください。-mapやIDEを使う場合は、パスが一致している必要があります(下記)。
Dockerのパス。
bin/jumphpはコンテナ内の/workspaceにプロジェクトをマウントするので、デバッガーはfile:///workspace/...と報告します。IDEとbin/jumphp debugはこれをプロジェクトのファイルへ自動で対応づけ、指定するパスはプロジェクトからの相対パスです。dbgp mcpだけを使う場合は、フォルダーを対応づけます: dbgp mcp -map /home/you/project=/workspace。
PHP 8.6(asyncランタイム)。
PHP Debuggerはここでは動かず、Xdebugが使われます。PHP Debuggerを使うには、デフォルトのランタイム(PHP 8.5)でデバッグするか、そのセッションの間だけruntime: asyncを外してください。
ブラウザーのゲーム。
デバッガーはデスクトップランタイムで動きます。ブラウザーでは、デスクトップ上でbin/jumphp testかshotを使ってバグを再現してください。
あわせて コードを書く、実行する、テストする、IDE の Claude、IDE Remote もご覧ください。