Dockerで構築したLaravel環境に、PHPStormでステップ実行デバッグを仕掛ける

元記事 [Windows10 に PHP7+Laravel環境をDockerで構築](https://qiita.com/yagrush/items/7449e540b69832735866)
← 元元記事 [最強のLaravel開発環境をDockerを使って構築する【新編集版】](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)

# 目的

Dockerで構築したLaravel環境で実行されているPHPコードに対して、
JetBrains社の「PHPStorm」からステップ実行デバッグができるようにしたい。

## ステップ実行デバッグとは

* コードの好きな行で実行を停止させて、その瞬間の変数リストや変数の中身を覗き見する。
* 1行ずつ実行させて、どこでエラー落ちするか追跡する。

といったことができる、例のアレ↓です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/5399c959-18b4-e534-1fec-5bb7fb1a2881.png)

# 概要

今回、PHP定番デバッグツール xdebug を使用して実現していきます。
（Laravel最新版には他にもイケてるデバッグツールがあると思いますが、諸事情で古いバージョンのLaravelを使用しなければならなかったので:sob:）

PHPはサーバーサイドプログラミング言語なので、サーバー側に xdebug をインストールしてデバッグ情報を吐き出させるようにしないといけません。

加えて今回はWindowsやMacに構築したDockerコンテナの中でサーバーを動かしているので、ちょっとだけ工夫が必要です。

# 環境

* 冒頭に書いた元記事および元元記事の手順でLaravel環境を構築済であること。
* PHPStorm最新版を使って開発している方。（Windows版 / Mac版 両方で動作確認済。）
* 開発環境や検証環境。（本番環境ではデバッグツールを入れる必要は無いので。）

# 方法

## サーバー側作業

### PHPサーバーに xdebug インストール&有効化する設定を追記する。

PHPサーバーは今回 Docker で構築されるようになっているので、その設定ファイルをいじります。
2行ほど追記します。

```Dockerfile:docker-laravel/infrastructure/docker/php/Dockerfile
・
・
・
RUN apt-get update && \
  apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  locale-gen en_US.UTF-8 && \
  localedef -f UTF-8 -i en_US en_US.UTF-8 && \
  mkdir /var/run/php-fpm && \
  docker-php-ext-install intl pdo_mysql mbstring zip bcmath && \
  composer config -g process-timeout 3600 && \
  composer config -g repos.packagist composer https://packagist.org && \
# ↓↓↓ 追記 ↓↓↓
  pecl install xdebug && \
  docker-php-ext-enable xdebug && \
# ↑↑↑ 追記 ↑↑↑
  composer global require hirak/prestissimo
・
・
・
```

### PHPサーバーの php.ini に xdebug 設定を追記する。

php.ini には「`host.docker.internal`というマシンからのデバッグ通信要求を受け付けてね」という設定を追加します。

「`host.docker.internal`って、そんなアドレスのマシン持ってないぞ…？」
と思うかもですが、ご安心ください。
最近の Docker Desktop をお使いであれば、自動でそういう設定をしてくれます。

これはDockerホスト、つまりお手元の Windows や Mac を指し示すようになっています。
（Dockerコンテナの中から`localhost`とやるとDockerコンテナ自身を指してしまいDockerホストを辿れないので、こういう機能を用意してくれています。）

```ini:docker-laravel/infrastructure/docker/php/php.ini
・
・
・
[Assertion]
zend.assertions = 1

[mbstring]
mbstring.language = Japanese

# ↓↓↓ 追記 ↓↓↓
[xdebug]
xdebug.idekey="PHPStorm"
xdebug.remote_host = "host.docker.internal"
xdebug.default_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 0
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_port = 9000
# ↑↑↑ 追記 ↑↑↑
```

### Laravel環境を起動しておく。

これは元記事のまま、コマンド実行するだけです。

```sh:初めて実行する場合
cd docker-laravel/infrastructure
make create-project
```

```sh:すでにcreate-projectを実行したことがある場合
cd docker-laravel/infrastructure
make remake
```

※Dockerfileやiniをいじったのでmake initではなくmake remakeにしておいています。

コマンドが完了するまでお待ちください。
数分かかるかもです。

## クライアント側作業（お手元のWindows/Mac）

### PHPStormを起動する。

ここで初めて起動してください。
もしすでに起動してdocker-laravelプロジェクトを開いてしまっていたら、再起動してください。
（Dockerビルド工程でインポートされたPHPライブラリ群がインクルードされていない場合があるので。）

### PHPStormで docker-laravel プロジェクトを開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/7145d22e-95d6-aba0-fa67-46acc01717be.png)

### メインメニューから設定画面を開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/c0296c94-135a-a039-3ec2-60eb916ae6c5.png)

### 左メニューから`Languages & Frameworks`→`PHP`を開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/8bbcde78-ee64-d983-bb68-093ccc086c2e.png)


### 画面右側の `+` を押す。

（ついでに、`Include Path`欄にPHPライブラリ群がずらーっとインクルードされているか念のため確認してください。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/3e654d2c-5efe-222d-f695-69be7aec932d.png)

### docker-laravel を選択して `OK` を押す。

今回のプロジェクトのルートディレクトリを丸ごとパスに追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/bc93bb40-4ac3-6a95-b82b-9b17d75f8713.png)

### 左メニューから`Languages & Frameworks`→`PHP`→`Debug`を開き、`xdebug`→`Debug port:` 9000 にする。

最初から 9000 だったらそのままでOKです。
次へ進みましょう。

余談ですがなぜ 9000 かというと、今回PHPコードを処理するのはポート9000で待ち受けている php-fpm というソフトだからです。WEBアクセスそのものはポート80で待ち受けているWEBサーバーソフト nginx が処理しますが、PHP処理だけ php-fpm に投げる、という動きになります。
（ちょっと前のモダン構成だと、Apache というWEBサーバソフトがポート80で待ち受け、WEBもPHPも一括処理するというのが多かったです。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/d7912a4a-a8fe-ce80-7967-666d8580578a.png)

### 左メニューから`Languages & Frameworks`→`PHP`→`Servers`を開き `+` を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/4f0e90ce-8e55-bc6d-2a82-a4ce8456c443.png)

### 以下の設定をして、最後に `Apply` ボタンを押す。

|設定項目|値|
|:--|:--|
|Name|docker-laravel|
|Host|localhost|
|Port|9000|
|Debugger|Xdebug|
|User path mappings|チェックON|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/647cc678-da11-2ee5-fb14-a64b7e94a048.png)

終わったら閉じてOKです。

### メインウィンドウ右上の `Add Configuration...` を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/b0850a35-b6dc-cc71-90e6-65c84071b6c1.png)

### 左ツリー上部の `+` を押して `PHP Remote Debug` を選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/8b47884b-f1f1-07f0-c874-84ab9bbce2f3.png)

### 以下の設定をして、最後に `Apply` ボタンを押す。

|設定項目|値|
|:--|:--|
|Name|docker-laravel|
|Filter debug connection by IDE key|チェックON|
|Server|docker-laravel|
|IDE key|PHPStorm|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/bdc54f47-caa6-e303-c562-b74f6dc0cd3f.png)

終わったら閉じてOKです。

### メインウィンドウ右上の `緑色の昆虫` ボタンを押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/ffc57815-8bf4-e68d-ed25-e9d1d422cfcd.png)

そうすると、

* `緑色の昆虫`ボタンの右のほうに`赤い■`ボタンが点灯します。
* メインウィンドウ下部にデバッグ情報小窓が展開されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/c64ac6f2-2bb1-fdfd-9853-9a372afdd57d.png)

これで、デバッグ中の状態になりました。
デバッグをやめるには`赤い■`ボタンを押せばOKです。

### ブラウザでPHPサーバーにアクセスしてみる。

http://localhost/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/cd6b9d47-802b-7693-2313-269c1b11fa6e.png)

普通なら Laravel のサンプルページが開くはずですが、ずっとアクセス中のように見えます。
実は、デバッガーが割り込んで処理を途中で止めているのです！

### デバッグ情報小窓→`Debugger`タブを開く。

お、デバッグ情報が来てますね！

ただ、何やらエラーが表示されています。
「サーバーコードと手元のソースファイルが関連付けられていないから追跡できないよ！」と怒られています。

なので、設定してあげましょう。
すぐ下の行に表示されている `Click to set up path mappings` を押して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/9e729001-42a9-00f2-e849-0069230fdba4.png)

### 以下の設定をして `OK` を押す。

1. この画面、出現当初はすごくウィンドウが小さいので、広げてあげてください。
2. `Use path mappings` にチェックを入れます。
3. 下部にプロジェクトファイルリストが出てくるので、`File path on server:` に示されているコードに相当するソースファイルを指定してあげます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/f185dc67-37de-82ad-7c78-67826fd2fdfd.png)

### 再度PHPサーバーにアクセスしてみる。

http://localhost/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/76356c0f-553a-e597-d63e-f2feb89f6834.png)

あれ、今度はすんなりWEBページが表示されて終わってしまいました。
でも大丈夫、正常です！

### ソースコードの該当行にブレークポイントを仕掛けてみる。

このページのソースコードは `index.php` ですね。
では `index.php` を開いて、停止させてみたい行の冒頭をクリックしてみてください。
`赤い●`が点灯します。

そうすると、その行にブレークポイントがセットされます。
ブレークポイントとは、ステップ実行デバッグにおいて「その行まで処理が来たら、一時停止してね」というマーキングです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/3b0dd991-8d92-26eb-ef75-e65a04c98b7f.png)


### 再々度PHPサーバーにアクセスしてみる。

http://localhost/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/15d2a7f0-cc16-97e5-f8c4-c524ebd51031.png)

来ました！
54行目で処理が一時停止され、その瞬間の変数などが丸見えです！

次のブレークポイントまで進めるなら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/0fa82ef3-57d0-8ce4-fcab-79d5a0a8316e.png)

次の行、次の行、と一行ずつ進めていくなら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553715/e1e2aefa-4033-0880-db86-47db658eacd5.png)

といったことも可能です。

それでは長くなってしまいましたが、今回はここまで。
お疲れ様でした:thumbsup: