PHPを今の会社で使い始めて約3ヵ月var_dumpでデバッグしてたマンです。
今回ちょっと時間があったのでVagrant上のPHPをNetBeans(Visual Studio Code 以下VSCode)でリモートデバッグできるようにしてみました。

目次

  1. 環境
  2. はじめに
  3. 前準備
  4. インストールと設定(サーバー:ゲストOS側)
    1. php.ini設定
    2. 設定確認
  5. インストールと設定(NetBeans)
    1. オプション
    2. プロジェクトのプロパティ
  6. ファイアウォール確認
  7. 実行 & 動かないとき
    1. 接続確認
    2. ブレークポイント確認
    3. NetBeans確認
    4. 設定に関してその他
    5. Webサーバーとか再起動
  8. Visual Studio Codeでのデバッグ
    1. PHP Debugインストール
    2. 設定
  9. その他

以下、会社でやったので(家にPHPの環境はないので)スクリーンショットとかは一切ないです。

環境


ゲストOSはUbuntuですが、Linux系だとコマンド違うくらいのハズです。

OSとかソフトとか 役割
Windows10 ホストOS
VirtualBox 5.0.20 仮想環境用
Vagrant 1.8.4 仮想環境用
Ubuntu 16.04 ゲストOS
Xdebug(バージョン解らん) PHPのデバッグ用。ゲストOSにインストール
NetBeans 8.1 IDE

ゲストOS上でPHP製のWebサイト(もしくはCLIがある)が構築されているものとします。
ホストOSでNetBeans(もしくはVSCodeその他IDE)を使用してデバッグします。
ホストOSとゲストOSはprivate network接続です。

ソースコードはVagrantのrsyncで同期をとっているものとします。別に同期取らなくてもデバッグのたびにアップロードってのがNetBeansでできるようです。
が、私はrsyncでやってるのでデバッグ都度アップロードってのはやってません。

と、長々書いてますが、仮想環境だろうがそうでなかろうが、大体下記に記述する通りでリモートデバッグできると思います。

はじめに


以下の辺りを知っておくと解り易いと思います。

XdebugDBGPプロトコル?を使用してクライアント(ホストOS)とサーバー(ゲストOS)で通信します。

  1. サーバー(ゲストOS)側のXdebugがクライアント(ホストOS)と通信確立(IDE側でデバッグを開始している必要がある)
  2. サーバー(ゲストOS)側のXdebugIDE上で設定したブレークポイントを確認
  3. サーバー(ゲストOS)側でPHPが実行されるとクライアント(ホストOS)のIDEに通信
  4. IDEでデバッグできる

つまり、クライアント(ホストOS)のIDEはサーバー(ゲストOS)のXdebugからの通信を受信する形になります。

前準備


PHPがデバッグ版でないことを確認します。

1
php -i | grep 'Debug Build'

Xdebugのインストール

インストールと設定(サーバー:ゲストOS側)


PECLというPHPの拡張ライブラリのコマンドでXdebugをゲストOSにインストールします。

1
pecl install xdebug

インストールに成功すると下記のような出力が確認できます。

1
2
3
4
5
Build process completed successfully
Installing '/usr/lib/php5/20131226/xdebug.so'
install ok: channel://pecl.php.net/xdebug-2.4.1
configuration option "php_ini" is not set to php.ini location
You should add "zend_extension=/usr/lib/php5/20131226/xdebug.so" to php.ini

この最後の行You should add "zend_extension=/usr/lib/php5/20131226/xdebug.so" to php.iniに書いてある通りphp.iniに設定を記述します。

php.ini設定

前述の通りXdebugの設定をphp.iniに記述します。
php.iniの場所は下記のコマンドで確認できます。

1
php -i | grep php.ini

php.iniの場所 php.iniの探し方

php.iniに下記を追記します。

1
2
3
4
5
6
7
8
9
10
11
zend_extension=/usr/lib/php5/20131226/xdebug.so

[XDebug]
xdebug.remote_autostart=On //1でもOK
xdebug.remote_enable=On
xdebug.remote_host=ホストのIP
xdebug.remote_port=9001
xdebug.remote_log=/var/log/xdebug.log
xdebug.remote_mode=req
xdebug.idekey=hoge //IDEで確認
xdebug.remote_handler=dbgp

Onの部分は1の記述でも動作します。
idekeyは各IDEで設定する値を記述します。NetBeansだとnetbeans-xdebugだったと思います。
portはデフォルト9000ですが、私はmongoexpressで使用しているので9001に変更しました。

設定確認

下記のコマンドで設定の確認を行います。

1
php -i | grep xdebug

インストールと設定(NetBeans)


NetBeansの設定です。VSCodeについては記事の最後に書きます。
この辺、スクリーンショットがあった方が解り易いのですが、なにぶん撮ってないので…

オプション

[オプション]->[PHP]->[デバッグ]で下記を変更します。

  • デバッガポート : サーバー側のXDebugで設定したポート
  • セッションID : サーバー側のXDebugで設定したセッションキー

最初行で停止の設定は初めの確認時はチェックしといてもいいですが、常に止まるようになるので後で外します。

プロジェクトのプロパティ

プロジェクトのプロパティを下記のように変更します。

  • ソース

    • ソースフォルダ : クライアント(要するにIDEで開いてるプロジェクト)のソースディレクトリ指定
  • 実行構成

    • 実行方法 : リモートWebサイト(FTP,SFTP)
    • プロジェクトURL : ブラウザで表示するURL
  • リモート接続先

    • ホスト名 : vagrantのIP
    • ポート : sshポート
    • 初期ディレクトリ : サーバー(ゲストOS)のプロジェクトルート
  • ファイルのアップロード : 手動

※デバッグ開始時にWebブラウザを毎回開かない場合は詳細設定でサーバーパスとプロジェクトパスのマッピングが必要です。
これは要するにクライアント(ホストOS)側のソースコードの場所とサーバー(ゲストOS)側のドキュメントルートを指定すればよいです。

またrsyncで同期取ってない場合はファイルのアップロード設定でデバッグ時にサーバー側に変更したコードをアップロードできる(と思われます。実際にやっ…)

ファイアウォール確認


サーバー(ゲストOS)側のポートとクライアント(ホストOS)のポートが許可されていることを確認します。
クライアント(ホストOS)は受信だけで大丈夫なはずです。

この辺りの設定は下記のサイト様が詳しいです。

【Xdebug】Windows 7のVagrant でリモートデバッグできない問題

実行 & 動かないとき


これでNetBeansでデバッグ実行すればブレークポイントでちゃんと止まってくれます。
…のはずですが、まあ一発ではうまくいかないんじゃないでしょうか。

ですのでXdebugのログを確認したりして対応します。
といっても、会社で確認したときの記憶しかないので以下ざっくりです。

接続確認

まず IDE側でデバッグを開始していない とログにはconnection time outと表示されます。
従って IDEでデバッグ開始した上で ログを確認します。

それでもconnection time outと表示される場合はxdebug.remote_hostあたりを見直してください。
なお、パスマッピングが上手くいってなくても接続自体はできます(あたりまえ)

ブレークポイント確認

接続が上手くいっている状態で、IDE側でブレークポイントを設定していると、Xdebugのログにどこにブレークポイントを張っているか表示されます。これが表示されていなかったら…どうしたらいいんでしょうかね…わかりません。

なお、パスマッピングが上手くいってなくても、どこにブレークポイントが張られているかはログに表示…されたと思います。(記憶があいまい)

NetBeans確認

NetBeansでデバッグ中にセッションID名 実行中が表示されていることを確認します。
さっきまで実行中だったのに接続を待っていますから進まない場合はNetBeansを再起動します。
原因はわかりませんが、設定が正しくても接続を待っていますから進まない場合があります。

接続が確立されててログにブレークポイントの個所も表示されていたら、ほぼ間違いなくパスマッピングの設定辺りが誤ってると思います。(断言はできない)ので、ひたすらNetBeansの設定を見直します。 (断言はできない)

設定に関してその他

Vagrantのポートフォワーディングの設定は不要ですので、不用意にいじくりまわしてVagrantの再起動とかいりません。

Webサーバーとか再起動

以下、十中八九再起動しなくても動くっぽい(?)ですが、それでもだめならWebサーバー等の再起動を行います。
なお、私の環境ではnginx + php-fpmでやってるので下記の2つを記述していますが、環境にあわせて適宜変えてください。

1
2
service php5-fpm restart
service nginx restart

Visual Studio Codeでのデバッグ


こっちはNetBeansほど設定することはないです。

PHP Debugインストール

拡張でPHP Debugをインストールします。

設定

プロジェクトのディレクトをを開きます。
デバッグアイコンから設定を押下します。launch.jsonというファイルが作成されるので以下を記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"version": "0.2.0",
"configurations": [
{
"name": "xdebug",
"type": "php",
"request": "launch",
"serverSourceRoot": "サーバー側のドキュメントルート",
"localSourceRoot": "${workspaceRoot}",
"port": 9001,
"log": true
}

]
}

serverSourceRootlocalSourceRootNetBeansでいうパスマッピングです。
なお"localSourceRoot": "${workspaceRoot}"という記述でクライアント側のコードはVSCodeで開いているディレクトを指定するという意味になります。

またxdebug.idekeyは使用しませんが指定していても問題ないです。
その他の設定はPHP Debugの公式サイトを頑張って読みます。

その他


当然ですがNetBeansVisual Studio Codeで同時デバッグはできません。