Xdebug完全掌握:なぜ動かない?を3分で根絶し、開発速度を極限まで引き上げるプロのトラブルシューティング&実践設定ガイド
テックリードの私たちが日々のコードレビューやアーキテクチャ設計と同じくらい、いや、それ以上に心を砕かなければならないもの。それは「開発フィードバックループの高速化」です。
`var_dump()` や `error_log()` を仕込み、ブラウザをリロードしてコンソールを確認する――。そんな前近代的なデバッグ手法を未だにチームメンバーが続けているとしたら、それは個人のスキル不足ではなく、「Xdebugの環境構築・設定の難解さ」という組織的負債を私たちが放置していることに原因があります。
今回は、Xdebugで最も多い「あれ、ブレークポイントで止まらない……」という絶望的な状況を秒速で打破するためのトラブルシューティングチェックリストと、IDE(VS Code / PhpStorm)のポテンシャルを限界まで引き出し、開発スピードを劇的に高める実践設定を全公開します。
—
1. なぜ動かない? Xdebug障害特定チェックリスト(理論と実務)
Xdebugが沈黙する時、それは必ず「通信の断絶」「設定ミス」「バージョンのミスマッチ」のいずれかが起きています。内部で何が起きているのかを理解すれば、勘に頼ったデバッグは不要になります。
チェック1:IDEとのポート競合と `xdebug.client_port` の死角
- 内部挙動: Xdebugは、PHPスクリプトが実行されると、設定されたIPとポート(デフォルトは `9003`)に対して外部からTCPコネクションを張ろうとします。この時、ローカルの別プロセス(古いPHPプロセスや他のサービス)がすでにそのポートを占有していると、OSレベルでコネクションが拒絶されます。
- 解決策:
ローカル環境のポート競合を確認し、明確に指定します。特にDocker環境とホストOS間では、ルーティングのミスが多発します。
; php.ini または xdebug.ini での設定例
[xdebug]
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yes
; Dockerホストを明示的に指す(macOS/Windowsの場合は host.docker.internal が有効)
xdebug.client_host=host.docker.internal
; デフォルトの9003から変更する場合や、複数コンテナで競合する場合はここで調整
xdebug.client_port=9003
チェック2:CLI実行時のセッションID(DBGpクッキー)の不一致
- 内部挙動: ブラウザからのリクエストであれば拡張機能が自動でクッキー(`XDEBUG_SESSION`)を付与しますが、ArtisanコマンドやPHPUnitなどのCLI実行時は、手動でトリガーを引くか、環境変数を渡す必要があります。
- 解決策:
CLIで実行する際は、環境変数 `XDEBUG_TRIGGER` を付与して強制的にデバッグセッションを開始させます。
ターミナルからXdebugを強制発動させてPHPUnitを実行する例
XDEBUG_TRIGGER=1 php artisan test
チェック3:ログによる「通信の可視化」
原因を推測で解決しようとしてはいけません。Xdebug自体の通信ログを出力させ、IDEまでパケットが届いているかを1秒で確認します。
; 通信の成否を完全に暴くための診断用設定
xdebug.log=/tmp/xdebug.log
xdebug.log_level=7
`/tmp/xdebug.log` を `tail -f` で監視しながらリクエストを送れば、「Connection refused」なのか「IDEが応答していない」のかが一撃で判明します。
—
2. 開発スピードを劇的に高める神プラグインとショートカット
Xdebugが動くだけでは不十分です。ここからが真の生産性向上フェーズです。キーボードから手を離さず、思考のスピードでデバッグを遂行するための環境を構築します。
VS Code 必須拡張機能と設定
1. PHP Debug (felixfbecker.php-debug)
- 標準的なDBGpプロトコルクライアント。これなしでは始まりません。
2. PHP Intelephense
- 高速な補完だけでなく、ジャンプ機能とXdebugのコンテキストがシームレスに連携します。
PhpStorm(選ばれしプロの選択)
PhpStormを使う場合、プラグインを追加せずとも標準で最強のデバッガーが内蔵されていますが、「Incoming Connections(受信接続)」のリスニングアイコン(電話の受話器マーク)を常時ONにしておくことが鉄則です。
—
3. チーム開発で役立つ設定の共有化ルール
「自分の環境では動くのに、新人A君の環境では動かない」――この不毛なコストを排除するため、設定はすべてリポジトリにコードとしてコミットします。
VS Code用 `.vscode/launch.json` (ベストプラクティス構成例)
チーム全員が同じ設定でデバッグを開始できるよう、Docker環境を前提とした頑健な設定をプロジェクトルートに置きます。
{
“version”: “0.2.0”,
“configurations”: [
{
“name”: “Listen for Xdebug (Docker Path Mapping)”,
“type”: “php”,
“request”: “launch”,
“port”: 9003,
“pathMappings”: {
// コンテナ内のソースコードの絶対パスと、ローカルのワークスペースを完全に一致させる
“/var/www/html”: “${workspaceFolder}”
},
“log”: false,
// ステップ実行時にベンダーディレクトリやフレームワークのコアに入り込まないための除外設定
“ignore”: [
“/vendor//.php”
]
}
]
}
Docker Compose (`docker-compose.yml`) でのXdebug一元管理
開発環境のコンテナ自体にXdebugを組み込み、環境変数でON/OFFを制御できるようにします。
version: ‘3.8’
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
volumes:
- .:/var/www/html:delegated
environment:
# 開発者ごとに上書き可能にしつつ、デフォルトでXdebugを有効化
- XDEBUG_MODE=debug
- XDEBUG_CLIENT_HOST=host.docker.internal
- XDEBUG_CLIENT_PORT=9003
networks:
- app-net
networks:
app-net:
driver: bridge
—
4. プロが実践する、Xdebugを活用した超高速開発テクニック
最後に、単なる「バグ取り」を超えて、「未知のレガシーコードを10分で完全に理解する」ためのプロの技を伝授します。
1. 条件付きブレークポイント(Conditional Breakpoints)の活用
ループ処理の500回目でバグる現象に対して、単純にブレークポイントを貼ると500回クリックし続ける地獄を見ます。「`$id === ‘target_uuid’`」という条件式をブレークポイントに設定し、ピンポイントで止める技術をマスターしてください。
2. ウォッチ式(Watch Expressions)でドメインモデルの状態を監視
複雑なオブジェクトの状態変化を追う際、評価式に `$order->calculateTotal()` などを登録しておけば、ステップ実行のたびにリアルタイムで値が再計算され、副作用の発生箇所を瞬時に特定できます。
結びに代えて
Xdebugの設定とトラブルシューティングは、一度マスターしてしまえばチーム全体に半永久的な開発効率の向上をもたらすレバレッジの効いた投資です。
「動かない」と悩む時間は今日で終わりにしましょう。完璧にチューニングされたデバッグ環境を手に入れ、ビジネス価値を生むコードの執筆に全脳のエネルギーを注いでください。