PHP × Xdebug × Docker × VSCodeで快適な開発環境をつくってみた


## はじめに

Rails でポートフォリオを作成してエンジニア転職をした[すず](https://twitter.com/suzuo_12)です。
現在は Laravel を主に使用していますがデバッグが捗らない...。
PHP でも Rails の `pry-rails` みたいに簡単にデバッグをしたかったので Xdebug を導入しました。

## 目次

- はじめに

- 目次
- 環境
- 前提条件
- ディレクトリ構成
- 準備
    - プロジェクト作成
    - 必要ファイル作成
- 拡張機能
- Docker環境構築
    - docker-compose.yml

    - Dockerfile
- コンテナ接続
- 設定ファイル
    - php.ini
    - xdebug.ini
    - devcontainer.json

- launch.json
    - 使い方

- おわりに
- 参考文献

## 環境

- macOS Catalina 10.15.7
- windows10 pro
- docker
- Xdebug 3系

## 前提条件

- Docker 環境
    - docker-compose.yml
    - Dockerfile

## ディレクトリ構成

```:このような構成を想定
.
├── .devcontainer
│   └── devcontainer.json
├── app
│　　　　　　├──　.vscode
│　　　　　　│   └── launch.json // 後述しますが、VSCodeの左のバーにある虫マークをクリックすると生成されます。
│　　　　　　└──　addNum.php      // デバッグテスト用のファイル
├── docker
│   └── php
│        ├── Dockerfile
│        ├── xdebug.ini
│        └── php.ini
└── docker-compose.yml

```

## 準備

#### プロジェクト作成

プロジェクトを作成していきます。プロジェクト名はお好きな名前で大丈夫です。ここでは **「php_xdebug_app」** という名前で進めていきます。

```shell:ターミナル
mkdir php_xdebug_app
cd php_xdebug_app
```

#### 必要ファイル作成

全体の見通しを良くするためファイルを始めに作成していきます。
作成ははじめに載せたディレクトリ構成に沿った形で作成しています。

```shell:ターミナル
touch docker-compose.yml
mkdir docker/php
touch docker/php/Dockerfile
touch docker/php/php.ini
touch docker/php/xdebug.ini
touch .devcontainer/devcontainer.json

# プロジェクトパス(デバッグしていきたいファイルなどを格納します。)
mkdir app
```

## 拡張機能
以下の VSCode の拡張機能が必要になりますのでインストールをしてください。

- PHPでデバッグをするのに必要になります。 

https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug

- コンテナ内に入るのに必要になります。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack


## Docker環境構築

#### docker-compose.yml

```yml:docker-compose.yml
version: "3.8"

services:
  php:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    volumes:
      - ./app:/var/www/html
    ports:
      - "8000:80"
```

#### Dockerfile

```dockerfile:docker/php/Dockerfile
FROM php:7.4-fpm

WORKDIR /var/www/html

RUN apt-get update \
  && apt-get install -y libonig-dev libzip-dev unzip \

# xdebug install
  && pecl install xdebug \
  && docker-php-ext-enable xdebug

# composer （今回は使用しませんが。。）
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

# docker-compose.ymlで指定した volumes と同じように書いてください。
# COPY [コピーする(ローカル)] [コピー先(コンテナ内)]　（詳しくは参考文献をご覧ください。）
COPY ./app /var/www/html
COPY ./docker/php/php.ini /usr/local/etc/php/php.ini
COPY ./docker/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

```

https://docs.docker.jp/engine/reference/builder.html#copy

https://www.tohoho-web.com/docker/dockerfile.html#copy

## 設定ファイル

#### php.ini

PHP の設定ファイル。

```ini:docker/php/php.ini
display_errors = On
display_startup_errors = On
max_execution_time = 30
session.gc_divisor = 1000
session.sid_bits_per_character = 5
output_buffering = 4096
memory_limit = 128M
upload_max_filesize = 64M
post_max_size = 64M
max_input_vars = 1000
log_errors = On
error_log = /dev/stderr
error_reporting = E_ALL
expose_php = On
zend.exception_ignore_args = Off
```

#### xdebug.ini

xdebug の設定ファイル。

```ini:docker/php/xdebug.ini
xdebug.client_host = host.docker.internal
xdebug.start_with_request = yes
xdebug.mode = debug
# port 番号はデフォルトで9003番ですがわかりやすいように明示的に書いています。9003ではなくても空いているポートなら大丈夫です。
# 後述する .devcontainer/devcontainer.json　に書く port と同じにしてください。
xdebug.client_port = 9003
xdebug.log = /var/log/xdebug.log
```

#### devcontainer.json

VSCodeがDockerコンテナに接続するための設定ファイル。

```json-doc:.devcontainer/devcontainer.json
{
	"name": "php_xdebug_app",           // お好きな名前
	"dockerComposeFile": [              // docker-compose.ymlのパスを記載
		"../docker-compose.yml",
	],
	"service": "php",                   // docker-compose.yml に記載しているサービス名で起動したいコンテナ
	"workspaceFolder": "/var/www/html", // 作業するパス
	"forwardPorts": [                   // xdebug.iniに書いたport番号と同じにする
		9003
	],
	"extensions": [                     // コンテナ内で使用したい拡張機能、お好みに合わせて設定してください。
		"felixfbecker.php-debug",
		"coenraads.bracket-pair-colorizer-2",
		"oderwat.indent-rainbow",
		"streetsidesoftware.code-spell-checker",
		"mosapride.zenkaku"
	]
}

```

## コンテナ接続

Docker環境を構築し、設定ファイルも作成したのでいよいよデバッグ機能を使用する環境（PHPコンテナ内）に入ります。

その前にコンテナをビルドして立ち上げておきましょう。以下のコマンドを叩いてください。

```sh:ターミナル
# build
docker-compose build

# コンテナ立ち上げ
docker-compose up
```

以下のような手順でコンテナ接続していきます。文字だけですと伝わらない部分あるかと思いますので Gif を作成しました。ぜひご覧ください。
（※ お使いの環境によって青い表示といっている部分が青くなかったらすみません。適宜対応していただけると助かります。）

1.　VSCode画面左下にある青いマークをクリック 
2.　`Reopen in Container` をクリック　
3.　しばらく立ったら画面遷移して左下の青い表示が `devcontainer.json` で設定した name と同じになっていたらコンテナと接続できています。

[![Image from Gyazo](https://i.gyazo.com/02dc6d80b79268e2fec7aa3e284a54bc.gif)](https://gyazo.com/02dc6d80b79268e2fec7aa3e284a54bc)

## launch.json

デバッグするのにも設定ファイルが必要になります。
**launch.json**作成していきます。

VSCode の左側のパネルに虫マーク (実行とデバッグ) があります。これをクリックすると **launch.json** の作成を求められるかと思うので作成を押してください。わかりにくい場合はディレクトリ構成に合わせてファイルを作成していただいても大丈夫だと思います。

```json-doc:app/.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "XDebug on docker", // お好きな名前
      "type": "php",              // 今回はPHPなので
      "request": "launch", 
      "port": 9003,               // portはxdebug.iniで設定したportと一緒にする
      "stopOnEntry": true,        // デバッグが有効なときにプログラムを中断する
    }
  ]
}
```

以上でデバッグができるようになります。

#### 使い方

言葉だけでは伝わらない部分があると思いますのでこちらも Gif を載せておきますので参考にしていただけたら幸いです。

1. 変数など値を確認したいところにブレークポイント（赤ポチ）を置く
2. 左のバーにある虫マークをクリック
3. 左上に再生ボタンが現れるのでクリック(下のバーがオレンジ色に切り替わる)
4. テストなどで動作を確認してみる。

簡単なプログラムを作成したので動作確認などでお使いください。
数字を足して出力するだけのプログラムです。このファイルを実行していきます。

```php:addNum.php
<?php

function addNum(int $num1, int $num2): int
{
    return $num1 + $num2;
}

$num1 = 1;
$num2 = 2;

$result = addNum($num1, $num2);
print_r($result);
```

[![Image from Gyazo](https://i.gyazo.com/724ef05ec5a1b7529296a571563cce8d.gif)](https://gyazo.com/724ef05ec5a1b7529296a571563cce8d)

[![Image from Gyazo](https://i.gyazo.com/5d416c5af622112f3179878e0df55ccd.gif)](https://gyazo.com/5d416c5af622112f3179878e0df55ccd)

横のバーに変数名と値など表示されますが、デバッグコンソールに変数名など入力することでも値をみることができます。


[![Image from Gyazo](https://i.gyazo.com/1ad4cde3289a49d254a02d37748fb1f5.png)](https://gyazo.com/1ad4cde3289a49d254a02d37748fb1f5)

## おわりに

`var_dump()` などで値を見るよりも簡単に確認することができるようになりました。
まだ使いこなせていませんが、開発をしていって慣れていきたいと思います。

参考までに今回のソースコードを[こちら](https://github.com/suzu12/php_xdebug_hands_on)にまとめさせていただきました。
お役に立つことができましたら幸いです。

## 参考文献

- [Docker VSCode PHP デバッグ 設定 xdebug](https://syslog.life/2021/04/12/docker-vscode-php-debug-settings-xdebug/#PHPini_%E4%BD%9C%E6%88%90)

- [vscodeでxdebug3のdocker環境を作る](https://qiita.com/islandryu/items/b5fbebb41f6d60fcf0c2)

- [WSL2+Docker+VSCode+PHPでXdebugを使用する際のホストにhost.docker.internalは使えない](https://zenn.dev/datsukan/articles/a479f3e98a70c4)

- [vscode↔Docker内PHPでリモートデバッグしたときにハマったこと](https://qiita.com/TakamiChie/items/9e53e1a3e180c5c8c88f)

- [PHPの開発効率化！VSCode+DockerでXdebugを使ってみよう](https://zenn.dev/cryptobox/articles/72682ff342e518)

- [Visual Studio CodeのRemote DevelopmentとDockerで快適な開発環境をゲット](https://tech-lab.sios.jp/archives/18677)


- [今回作成したプロジェクトのソースコード](https://github.com/suzu12/php_xdebug_hands_on)