🐡

xdebugをブラウザーからトリガーするための基本中の基本(設定に躓いてる人用)

に公開

はじめに

xdebugはブラウザーからトリガーして使う場合若干通信経路が複雑になるのと、最低限この設定が出来てないとxdebugが有効になってそうなのに全く使えないという事がある。そのためこの記事では設定がうまくいかない場合まず確認することとしてxdebugの設定状況および通信経路に着目し、その通信を確認した後でどのように解決していったらいいのか見て行くものとなっている。

WSL2とかのlinux環境がやっぱり欲しい

XAMPPに関してはよくわからんのでスルーするとして、

そうなるとWSL2かdockerデスクトップかみたいなのがローカル開発の基本になると思うがいずれにせよ基本的にlocalhostで通信するのでポートが遮断されているとかのトラブルは起き辛いものだ。ただしここではポートの通信を逐一確認するためにncというツールを使って実際の通信状況をデバッグを初める前にしっかり確認しておく所からはじめる。その点でもlinux環境がどうしても必要なため、ここではWSL2に限定した記事にまずはさせていただく。

なお、このツールはubuntu(debian)系だとnetcat-openbsdという名前になっているので、適時installしておくこと。

sudo apt update && sudo apt install -y netcat-openbsd
$ type nc
nc is hashed (/usr/bin/nc)

こんな感じになればok

WSL2による開発

冒頭で書いた通りwindowsネイティブのphp.exeは取り上げない。

ここではphpのweb開発ではもっとも一般的なlaravelをチュートリアルとして用意する。これもWSL2が導入されていれば簡単に用意する事ができる

大前提

phpは必要なのでapt install phpとかが必要なのはともかくとして、composerlaravelコマンドが導入されていること。これの環境構築に関してはページの無駄なので、ここでは取り上げない

WSL2内でlaravelを適当に用意する

というわけでlaravelコマンドが使える事を前提として、

laravel new testapp

みたいにして何でもいいのでlaravelのプロジェクトの雛形を展開する。その後で

cd testapp/
php artisan serve

とかすると

$ php artisan serve

   INFO  Server running on [http://127.0.0.1:8000].

  Press Ctrl+C to stop the server

こんな感じになるはずだ。ここでhttp://127.0.0.1:8000にアクセスすると何でもいいのでlaravelの画面が出てくるはずである、エラーでもいい


ここではエラーになってるけどまあ何でもよい

ここでブラウザーを通じてlaravelの画面が表示されているはずで、これに関してはhttp://localhostでもhttp://localhost:8000でも8888でも9000でも何でもいいんだけど、ブラウザーからwebアプリまでの通信は確立されているはずである。この部分に関しては

ブラウザー -> webapp

まで成立している事を意味するわけだが、xdebugはこの先の通信経路の確立が重要なのでここまでは普通に出来ている事が大前提である

xdebug環境の確認(phpinfo)

やはりここではまずxdebug環境が有効になっているかの確認を最初に行っておきたい。これはpublic/info.phpとかなんでもいいので好きなファイルを作成して確認するのが一応鉄板だろう

public/info.php
<?php phpinfo();

こんな感じで書いてアクセスすればよいはずだ

ここでWSL2+Ubuntu環境だと /etc/php/8.3/cli/php.iniとか /etc/php/8.3/cli/conf.dといったファイルをphp.iniの設定ファイルあるいはディレクトリとして設定されているのがわかる。今回はwebサーバーを経由せずartisan serveとか叩いているのでcliっていう風になるわけだが、いずれにせよ、phpinfo()内でxdebugが有効になっていない場合がほとんどだと思うので、有効になっていない場合は以下のように拡張をinstallする必要があるだろう。

sudo apt install php-xdebug

php-xdebugというのは一種の仮想パッケージというかメタパッケージのようなもので実際にはphp8.3-xdebugとかのようにバージョンに応じた拡張が入る、いずれにせよ以下のようにしてどこにinstallされたのかを確認可能である

$ dpkg -L php8.3-xdebug
/.
/etc
/etc/php
/etc/php/8.3
/etc/php/8.3/mods-available
/etc/php/8.3/mods-available/xdebug.ini
/usr
/usr/lib
/usr/lib/php
/usr/lib/php/20230831
/usr/lib/php/20230831/xdebug.so
/usr/share
/usr/share/doc
/usr/share/doc/php8.3-xdebug
/usr/share/doc/php8.3-xdebug/changelog.Debian.gz
/usr/share/doc/php8.3-xdebug/copyright

さて、ここでは /etc/php/8.3/mods-available/xdebug.ini に設定ファイルがある事がわかるので、これを編集する。 /etc/php/8.3/cli/conf.d ではないの?と思われた方は鋭いが、

$ ls -l /etc/php/8.3/cli/conf.d | grep xdebug
lrwxrwxrwx 1 root root 38 Jun 13 09:40 20-xdebug.ini -> /etc/php/8.3/mods-available/xdebug.ini

このような形でリンクされているので大丈夫な仕様になっている。いずれにせよ以下のように記述する

/etc/php/8.3/mods-available/xdebug.ini
zend_extension=xdebug.so

[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.log=/tmp/xdebug.log

xdebugの環境確認

ここで再度phpinfoを見てみよう


Step Debuggerがentabledになっている


127.0.0.1:9003とかになっている


xdebug.modexdebug.start_with_requestを確認

このように設定項目が正しく反映されているか十分確認すること

デバッガーが動作しているか確認する

ここでwebアプリの通信は前に記したように

ブラウザー -> webapp

こうなっているが、xdebugの通信は

ブラウザー -> webapp -> デバッガ

となっておりwebアプリからデバッガーに接続してくる。ここでの経路が先程セットした127.0.0.1:9003であり、ここの接続経路が確立できないと全くデバッグができない。ここが最初のちょっと難しい所だ

つまり127.0.0.1:9003でデバッガが待ち受ける必要があるのだが、通常は今日日vscodeを使う事になるだろう(phpstormはよくわからん)。ただvscodeだろうがphpstormだろうがvdebugだろうが何にせよ指定された経路(ここでは127.0.0.1:9003)の通信が確立してないとまったく動作しようがないので、まずここでは冒頭で導入したncコマンドを媒介させて通信できているかどうかを確認するのがトラブルが少ないだろうと思う

ここでssコマンドで現在の状態を確認すると

$ ss -tlpn
State       Recv-Q      Send-Q            Local Address:Port            Peer Address:Port      Process
LISTEN      0           4096              127.0.0.53%lo:53                   0.0.0.0:*
LISTEN      0           4096                  127.0.0.1:42297                0.0.0.0:*
LISTEN      0           1000             10.255.255.254:53                   0.0.0.0:*
LISTEN      0           4096                 127.0.0.54:53                   0.0.0.0:*
LISTEN      0           4096                  127.0.0.1:8000                 0.0.0.0:*          users:(("php8.3",pid=2688,fd=7))

こんな感じになっていた。ここでさらに1つターミナルを起動し

nc -l 127.0.0.1 9003

と打つとターミナルが応答待ちになって何も表示されない状態となるが、この時点でssを再度見ると

$ ss -tlpn
State    Recv-Q   Send-Q      Local Address:Port        Peer Address:Port   Process
LISTEN   0        4096        127.0.0.53%lo:53               0.0.0.0:*
LISTEN   0        1               127.0.0.1:9003             0.0.0.0:*       users:(("nc",pid=4026,fd=3))
LISTEN   0        4096            127.0.0.1:42297            0.0.0.0:*
LISTEN   0        1000       10.255.255.254:53               0.0.0.0:*
LISTEN   0        4096           127.0.0.54:53               0.0.0.0:*
LISTEN   0        4096            127.0.0.1:8000             0.0.0.0:*       users:(("php8.3",pid=2688,fd=7))

このように127.0.0.1:9003が表示されている。この時点で再度info.php的なものをリロードしてみると...?

こんな感じでxmlが表示され、なおかつブラウザーがグルグル回ってる状態になるはずだ


停止している

ここでnetstatをCtrl+cとかで割り込むとブラウザーは素直に表示に戻ることだろう。ここまで出来て初めてxdebugが機能する準備が整ったということになる。

vscodeで確認してみよう

vscode + wsl2の場合はwsl拡張が必須だから導入しておくこと

また、phpdebugも必要なのでこれも導入する。2つあるけどポピュラーな方で

WSL2への接続

ctrl+shift+pとかで接続し、当該のlaravelディレクトリーを開くと以下のようになるはずだ

ただし、開いただけでは9003はlistenしていない、ってことはvscode開いただけではvscodeでデバッグできないというのがこの時点で理解可能なはずである。

 ss -tlpn
State    Recv-Q   Send-Q      Local Address:Port      Peer Address:Port  Process
LISTEN   0        4096        127.0.0.53%lo:53             0.0.0.0:*
LISTEN   0        511             127.0.0.1:41061          0.0.0.0:*      users:(("node",pid=4359,fd=18))
LISTEN   0        4096            127.0.0.1:42297          0.0.0.0:*
LISTEN   0        1000       10.255.255.254:53             0.0.0.0:*
LISTEN   0        4096           127.0.0.54:53             0.0.0.0:*
LISTEN   0        4096            127.0.0.1:8000           0.0.0.0:*      users:(("php8.3",pid=2688,fd=7))

9003が見当たらない

vscodeでデバッグするためには.vscode/launch.jsonが必要

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug",
      "type": "php",
      "request": "launch",
      "port": 9003,
      "pathMappings": {
        "/your/path/to/testapp": "${workspaceFolder}"
      }
    }
  ]
}

こんな感じで書いて、保存する。/your/path/to/ は正しくWSL2の環境と合わせること。

さらにinfo.phpを改変し

public/info.php
<?php
$var = "This is a test variable";
var_dump($var);
phpinfo();

こんな感じにしてみよう。この段階でvscodeのデバッグしたい行に赤丸を付けることができる。これがブレークポイントというやつになる

デバッグしてみる

左の三角みたいになってる奴から辿ってListen for Xdebugの左の緑の三角を押す。この時点でまずssで確認してみよう

$ ss -tlpn
State    Recv-Q   Send-Q      Local Address:Port      Peer Address:Port  Process
LISTEN   0        4096        127.0.0.53%lo:53             0.0.0.0:*
LISTEN   0        511             127.0.0.1:41061          0.0.0.0:*      users:(("node",pid=4359,fd=18))
LISTEN   0        4096            127.0.0.1:42297          0.0.0.0:*
LISTEN   0        1000       10.255.255.254:53             0.0.0.0:*
LISTEN   0        4096           127.0.0.54:53             0.0.0.0:*
LISTEN   0        4096            127.0.0.1:8000           0.0.0.0:*      users:(("php8.3",pid=2688,fd=7))
LISTEN   0        511                     *:9003                 *:*      users:(("node",pid=7768,fd=19))

するとこんな感じで9003が見えるようになった。この状態でinfo.phpを開いてみると


画面が停止している

ここでは新たに開き直してgoogleが見えてるけどいずれにせよ画面が停止し何も表示されない、これが正解だ、画面が停止しない場合はここにいたるまでの何かの設定がおかしい可能性がある。

vscodeに戻ると、当該の行で止っている。左の変数を見るとまだ $var には何も入っていないが、ステップオーバーすると

こんな感じで変数の内容が左ペインに表示されているし、下のパレットでも$varとか打つと

このようになるというわけだ

デバッグを停止し、9003とかのlistenをやめるには

赤い四角形を押すとよい

以上

ここまで主にvscodeを使ったブラウザデバッグ手法を見てきたが、これはphpstorm(使ったことないけど)でも、vdebugなんかでも同じ仕組みになっているはずだから、まずサーバーからデバッガへの通信をまともに受信できているのかの確認がどうしても必須であると言える。そのためにはncコマンドは非常に強力であり、本番のデバッガを媒介させる前にこのコマンドで正しくデバッガー用のxmlを受信できているのか確認しておくのが非常に重要になるだろう。これはlocalネットワークでトラブルが少ないwsl2や、たぶんXAMPPとかだけで開発しているとあんまりハマらないところかもしれないが、たとえばこれがdockerコンテナーからのデバッグ、さらにはリモートから直接デバッグしたいとかいう場合でも結局このTCP通信さえ確立してしまえば出来るということになるはずなわけで、この通信の確認は非常に便利でありまた重要であるわけだ。

ここではおそらくもっとも簡単なWSL2環境のみ取り上げて解説したが、そのうちもうちょっと複雑な開発環境に対するデバッガの起動方法も書く、かも。需要は限りなく少ないはずではあるが!

Discussion