CodeIgniter
xdebug
docker

Xdebug入門 カンタンな使い方

こんばんは。滑り込みですが、
この記事はCodeIgniter Advent Calendar 2017の19日目です。
この記事単体でも読めますが、9日目11日目の続きとしても読める様に書いていきます。

CodeIgniterは基本的なPHPの構文とClassの概念が分かっていれば使い始める事が出来るフレームワークなので、学習コストはかなり低い方だと思います。

初心者でも理解しやすい・触りやすいフレームワークと言えますが、もし初心者の頃から変わらず var_dump(); しまくるプリントデバッグをしているなら、デバッガを使ってみるとより快適な開発が出来ます。

この記事ではDockerを使ってXdebugが動くPHP開発環境を作り、そこでCodeIgniterを動かす事でXdebugの使い方を紹介します。

Dockerで開発環境を作る

docker-composeを使います。開発マシンはMacでDocker for Macを使っている想定です。

docker-composeの設定

docker-compose.yml は以下の通り。

version: '2'

services:
  dev-with-xdebug:
    container_name: "codeigniter-xdebug"
    image: webdevops/php-apache-dev:ubuntu-16.04
    working_dir: /app
    volumes:
      - ./:/app
      - ./custom.ini:/opt/docker/etc/php/php.ini
    ports:
      - "80:80"

Dockerイメージには、既にXdebugをインストールしたPHPが入っている webdevops/php-apache-dev を使っています。
イメージの中身が気になる方は GitHubDocker Hubを見てみて下さい。

このイメージではドキュメントルートが /app なので、 docker-compose.yml を置く場所(./)をコンテナ内の /app と共有しています。

また、PHPの設定でデフォルトから変える物は custom.ini に書き出して、Dockerコンテナ内に渡します。
webdevops/php-apache-dev:ubuntu-16.04 のDockerイメージの場合は、PHPが /opt/docker/etc/php/php.ini という空のINIファイルを読んでいるので、ホスト側の custom.ini をそこへマウントしています。

Xdebugの設定(.ini)

custom.ini にXdebugの設定を記述していきます。内容は以下の通り。

xdebug.remote_connect_back = 0
xdebug.remote_host = docker.for.mac.localhost
xdebug.remote_port = 9000
xdebug.remote_handler = "dbgp"
xdebug.remote_autostart = 1
xdebug.remote_log = /app/application/logs/xdebug.log
xdebug.idekey = "docker"

MacでDocker for Macを使っているという想定で xdebug.remote_host = docker.for.mac.localhost の値を指定していますが、他の環境の場合は適宜変更して下さい。
Dockerコンテナ内から見たホスト側のIPアドレスやホスト名が入るかと思います。

また、ドキュメントルートが /app なので、そこに置いたCodeIgniterの application/logs/ の中にXdebugのログを書く様に指定しています。

そしてXdebugが9000番ポートを使う様に指定していますが、これは webdevops/php-apache-dev のDockerイメージの方で穴が開いているので、 docker-compose.yml の方でEXPOSEの設定を書かなくても大丈夫です。

コンテナ起動

この docker-compose.ymlcustom.ini を使ってローカル開発環境を建てます。

$ cd ~/Desktop
$ wget https://github.com/bcit-ci/CodeIgniter/archive/3.1.6.zip
$ unzip 3.1.6.zip
$ cd CodeIgniter-3.1.6
$ vim docker-compose.yml
$ vim custom.ini
$ docker-compose up -d

コンテナが起動したか確認

$ docker ps
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS                                   NAMES
505b74f892b9        webdevops/php-apache-dev:ubuntu-16.04   "/entrypoint super..."   39 minutes ago      Up 39 minutes       443/tcp, 0.0.0.0:80->80/tcp, 9000/tcp   codeigniter-xdebug

$ docker-compose ps
       Name                  Command           State                   Ports
--------------------------------------------------------------------------------------------
codeigniter-xdebug   /entrypoint supervisord   Up      443/tcp, 0.0.0.0:80->80/tcp, 9000/tcp

http://localhosthttp://0.0.0.0:80 )にアクセスすれば、見慣れたCodeIgniterのウェルカムページが出ているハズです。
9000番ポートも穴が空いていますね。
今回はHTTPSで通信しないので、443番は使いません。

エディタの設定

ここまでの設定で、コンテナ内でPHPが実行されるとXdebugが走り、コンテナから見た docker.for.mac.localhost:9000 へ向けて通信をしようとします。
その様子は application/logs/xdebug.log に書き込まれているハズです。

なので、エディタ側でその通信を受け取ればOKです。
ここからは個々のエディタの設定に依るので省きますが、肝心なのは

  • エディタ側から見たら localhost:9000 (0.0.0.0:9000) から通信が飛んでくる
  • idekeyは docker
  • パスのマッピングは /app~/Desktop/CodeIgniter-3.1.6

辺りでしょうか。
僕の場合はVimで joonty/vdebug プラグインを使っているので以下のような設定値になります。

let g:vdebug_options = {
\    "port" : 9000,
\    "debug_file_level" : 2,
\    "debug_file" : '~/.vim/vdebug.log',
\    "ide_key" : 'docker',
\    "path_maps" : {
\      '/app': '/Users/ayato/Desktop/CodeIgniter-3.1.6',
\    },
\}

Xdebugを使う

手順としては

  1. 解析したい場所のコードにBreakPointを打つ
  2. エディタでXdebugからの通信を待ち受ける
  3. PHPを実行させる(ページの再読込みする等)
  4. BreakPointを打った所でPHPが中断するので、そこで変数の中身を調べたり、その時点での関数の実行結果を確認したりする

といった感じです。
都度 var_dump(); を書くよりも素早く色んな情報を引き出せるので開発スピードが上がるでしょう。

2つ例を出します。

例: application/views/welcome_message.php

スクリーンショット 2017-12-19 22.41.58.png

こんな感じで85行目にBreakPointを打ちました。この状態で
エディタの方でXdebugからの通信を待ち受けつつ、 http://localhost を開けば解析が始まるハズです。

BreakPointを打った85行目では定数 ENVIRONMENT によって振る舞いが変わっているので、予想外の振る舞いをした時はこの中身をチェックすると良いでしょう。
慣れるとわざわざ var_dump(); するより圧倒的に楽です。

例: application/controllers/Welcome.php

スクリーンショット 2017-12-19 22.57.14.png

23行目にBreakPointを打ちました。
ここまで解析を進めた状態でStep inすると、このview関数の中に入って確認する事が出来ます。

スクリーンショット 2017-12-19 23.00.29.png

application/controllers/Welcome.php$this->load->view()system/core/Loader.php で定義される関数 view() なので、Step inするとそこまでジャンプしていきます。

Step in / Step out / Step over を駆使すれば、おかしな挙動をしている部分を速く見つける事ができるかもしれません。

おわりに

いかがでしょうか?
デバッガは最初は動作の仕組みを勉強する所から初めないといけませんが、慣れればプリントデバッグよりも遥かに速くコードの挙動を調べる事が出来ます。

また、CodeIgniterはコアの部分でも複雑な事はほとんどしていないので、デバッガがあればその挙動を追いかけて勉強する良い教材になると思います。

この記事がデバッガ初心者の方の助けになれば幸いです。