[CakePHP3] CakePHP3環境構築入門 ～初心者がVSCodeでリモート上のCakePHPアプリをステップ実行できるようにするまで。～

# 環境構築は大変！
[こちら](https://qiita.com/takmt/items/0858dbd3c53cabaa4395)でも記載しましたが、非常に環境構築が大変だったので、CakePHPのステップ実行までのやり方を記載しておきます。
色んなサイトを見ながら構築するのもいいのですが、
本ページの目的はオールインワンで構築方法の方法を紹介する事です。
※多くの項目は [ここで記載した内容](https://qiita.com/takmt/items/0858dbd3c53cabaa4395)と同じです。

# 環境構築の前提

下記条件で環境構築で行います。
Windows10上にはVirtualBoxとVSCodeだけインストールを行い、
メインはCentOS7.6上にnginxサーバーを立てホストOSからステップ実行を行います。

##### ホストOS
* Windows 10
* VirtualBox 6.0
  * ネットワークはブリッジアダプター
* VS Code 1.33.1

##### ゲストOS(VirtualBox上にインストールするもの)
* CentOS 7.6
  * userというユーザー名を作成してます。
* PHP 7.3.5(Remiリポジトリからインストールします。)
* Composer 1.8.5(最新バージョン)
* CakePHP 3.7 (最新バージョン)

##### 筆者の能力
* CakePHPをこれから始めようとする完全初心者。
* 過去CentOS6を操作した経験あり。
* 最近CentOS7を操作した経験あり。

##### ここでは伝えない事
* Vagrantを使った環境構築
  - vagrantで[この問題が何度も発生した](https://qiita.com/leon-joel/items/4de455c507c85f78b3d5)為。
* VirtualBox上にCentOS7をインストールする方法
  - あくまでもVirtualBox上にCentOS7をインストールした後からの説明になります。

# 以下環境構築方法

### CentOS 7.6の初期設定(CentOS7側)
rootでログイン後 /etc/sysconfig/network-scripts/ifcfg-exxxxx0を編集しネットワーク接続できるようにします。
ここではviを使ってますが好きなエディタでよいです。

  ```  
  vi /etc/sysconfig/network-scripts/ifcfg-exxxxx0
  ```

  「ONBOOT = no」の行を「ONBOOT = yes」に変更して保存します。

その後再起動を行う。

  ```sh
  reboot 
  ```

再起動後 ip addrコマンドで出てきたIPアドレスを元にRLoginなどのターミナルソフトからリモートで接続可能です。

![0001.net setting.png](https://qiita-image-store.s3.amazonaws.com/0/383232/bcce7cdc-6719-aa2f-66d0-045e1548e2ae.png)

### 各種アプリケーションのインストール(CentOS7側)
rootでログインを行い、CentOS7上で必要と思われるアプリケーションを一気にインストールします。

  ``` sh:立ち上げ直後
  yum -y update 
  yum -y install telnet vim
  yum -y install epel-release
  yum -y groupinstall "Development Tools"
  yum -y install dkms bzip2 gcc make kernel-devel kernel-headers mariadb-devel mariadb-server sqlite-devel sqlite nodejs nginx git gcc gcc-c++ openssl-devel readline-devel
  ```
※mariadbなどは後々使うことを想定してインストールしています。


### 一般ユーザーがsudoコマンドを使えるようにする。(CentOS7側)
下記コマンドを入力し、

  ```sh
  visudo
  ```

```
root    ALL=(ALL)       
user    ALL=(ALL)       #この行を追加して保存
```

上の2行目をテキストに入力し保存します。


### ホストOSのフォルダをゲストOSから参照できるようにする。(CentOS7+Windows10側)

[この記事](https://qiita.com/takmt/items/302ebdf05c0cfebf4547#%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E6%96%B9%E6%B3%95-1)の②の環境構築方法を参考

#### Windows側(ホストOS側)の作業

1. Windows側(ホストOS側)に php_shareフォルダを作成する。
* プロパティからphp_shareフォルダを共有する。
* `\\windows側のIP\php_share` にアクセス可能か確認する。

#### CentOS側(ゲストOS側)の作業

1. `id user` コマンドを入力し userユーザーの uidとgidを取得する。
* `sudo vi /etc/fstab` コマンドでfstabを開く
* 下記をファイルの最下部に入力します。

  ```
  //<windowsのIPアドレス>/php_share /home/user/php_share cifs username=<windowsのユーザー>,password=<windowsのパス>,uid=<linuxユーザーのuid>,gid=<linuxユーザーのgid>,nobrl 0 0
  ```
ファイルを保存後、最後に再起動をします。

```
reboot
```

Windowsの共有フォルダ内に適当なテキストファイルを作成し、
CentOS7側から読めれば共有できています。

### CentOS7のファイアウォールの設定を行う。(CentOS7側)
CakePHPをステップ実行する為には下記のポート開放が必要です。

|ポート番号  | 用途   |
|-----------|---
|80         | ブラウザからHTTPアクセス可能なようにする  
|9000       | X-debug(PHPのステップ実行用ポート)      

まず9000番ポートを開放する設定ファイルを作りましょう。

```sh
sudo cp /usr/lib/firewalld/services/http.xml /usr/lib/firewalld/services/php-debug.xml
sudo vim /usr/lib/firewalld/services/php-debug.xml 
```


テキストエディタで開いたphp-debug.xmlの下記部分を
`<port protocol="tcp" port="80"/>`

下記のように変更し保存する。
`<port protocol="tcp" port="9000"/>`

php-debug.xmlで作成した内容とhttp(80番ポート)をファイアウォールに登録し確認を行います。

```sh
sudo firewall-cmd --add-service=http --zone=public --permanent
sudo firewall-cmd --add-service=php-debug --zone=public --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
```

最後の firewall-cmd --list-allを行った結果、
下記情報が出力されればポートの開放が出来ているはずです。
services: ssh dhcpv6-client **http php-debug**

この後rebootコマンドで再起動を行う。

```
reboot
```

再起動後、一般ユーザーでログインし sudo firewall-cmd --list-allで再度httpとphp-debugが登録されているか確認します。

```
sudo firewall-cmd --list-all
```

登録されていれば次にいきます。

### RemiリポジトリからPHPをインストールする。(CentOS7側)

下記はCentOS7にPHPをインストールするテンプレのような方法です。
とりあえずコマンドを入力すればよいです。

```
sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
sudo yum install -y --enablerepo=remi,remi-php73 php php-devel php-xdebug php-mbstring php-pdo php-gd php-xml php-mcrypt php-process php-intl php-mysql php-fpm 
```

### PHPの設定を修正する。(CentOS7側)

設定は[こちら](https://qiita.com/nao_tuboyaki/items/9615166e2374a565af80)のサイトが詳しいです。

```
sudo vim /etc/php.ini
```

下記行を修正する。

| 修正前                         | 修正後                              |
|-------------------------------|-------------------------------------|
| ;date.timezone                | date.timezone = "Asia/Tokyo"        |
| ;mbstring.language = Japanese | mbstring.language = Japanese        |
| ;mbstring.encoding_translation = Off | mbstring.encoding_translation = Off |
| ;mbstring.detect_order = auto | mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII |
| ;mbstring.substitute_character = none | mbstring.substitute_character = none |

### Composerのインストールを行う。(CentOS7側)

ComposerはPHP用のパッケージ管理ソフトです。
[公式ドキュメント](https://getcomposer.org/download/)の通りにインストールできます。

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

次にbinディレクトリにアプリ本体を移動させます。

```
sudo mv ./composer.phar /usr/local/bin/composer 
echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
```

動作確認をし問題なく実行できれば次にいきます。

```
composer --version
```


### PHP-Xdebugの設定を行う(CentOS7側)

`/etc/php.d/15-xdebug.ini ` の設定を修正して、Windows側からステップ実行を出来るようにします。

設定は[この方](https://qiita.com/castaneai/items/d5fdf577a348012ed8af)が詳しく説明してくださっています。

```
sudo vim /etc/php.d/15-xdebug.ini 
```

| 修正前                         | 修正後                              |
|-------------------------------|-------------------------------------|
| ;xdebug.max_nesting_level = 256 | xdebug.max_nesting_level = 1000   |
| ;xdebug.remote_autostart = 0   | xdebug.remote_autostart = 1         |
| ;xdebug.remote_connect_back = 0 | xdebug.remote_connect_back = 1    |
| ;xdebug.remote_enable = 0     | xdebug.remote_enable = 1           |


設定ファイルを修正すれば保存してエディタを終了しましょう。


### SELINUXを無効にする。(CentOS7側)

これはphp-fpmやnginxが正しく動作する為に必要なことですが、
詳しい方はselinuxを有効にしたまま問題なく動作させるようにすればよいと思います。
※筆者はselinuxの設定を有効化したまま正しく動作させる方法を知らないので無効にしちゃってます。

```
sudo vim /etc/selinux/config
```

`SELINUX=enforcing` を `SELINUX=disabled` に変更し、再起動を行う。

```
reboot
```



### サーバーアプリの設定変更を行う。(CentOS7側)

まずphp-fpmというPHP用サーバーアプリの設定を修正していきます。

#### php-fpm

```
sudo vim /etc/php-fpm.d/www.conf 
```

下記修正行です。

| 修正前                         | 修正後                                  |
|-------------------------------|----------------------------------------|
| user = apache                 | user = user                            |
| group = apache                | group = user                           |
| listen = 127.0.0.1:9000       | listen = /var/run/php-fpm/php-fpm.sock |
| ;listen.owner = nobody        | listen.owner = user                    |
| ;listen.group = nobody        | listen.group = user                    |


保存後、次にnginxの設定を行っていきます。

#### nginx

```
sudo vim /etc/nginx/nginx.conf 
```

下記ファイル全体です。
内容としては下記です。

* http://[CentOSのIP]/php/xxx.php にアクセスすれば、/home/user/php_share/php_program/xxx.phpを動作させる。
* http://[CentOSのIP]/cake にアクセスすれば、 /home/user/php_share/cake 内のCakePHPのアプリを動作させる。

```
user user;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        index index.html index.htm;

        location /cake {
            alias /home/user/php_share/cakeapp/webroot/;
            index index.php;
            access_log /home/user/nginx-cake-access.log;
            error_log /home/user/nginx-cake-error.log;
            
            location ~  ([^/]+\.php)$ {
                include fastcgi_params;
                root /home/user/php_share/cakeapp/webroot/$1;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            }
 
            location ~ /cake1/(.+)$ {
                root /home/user/php_share/cakeapp/webroot/;
                try_files /$1 /cake/index.php?$1&$args;
            }
        }

        location /php {
            root /home/user/php_share/php_program;
            access_log /home/user/nginx-php-access.log;
            error_log /home/user/nginx-php-error.log;

            location ~  ([^/]+\.php)$ {
                include fastcgi_params;
                root /home/user/php_share/php_program/$1;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            }
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}
```

保存後、下記コマンドを実行します。
※上のnginxの設定は動作する事は確認できていますが、正直これが理想系かと言われれば自信ないです。。。

```
sudo systemctl enable php-fpm
sudo systemctl restart php-fpm
sudo systemctl enable nginx
sudo systemctl restart nginx
```

### PHPの動作確認を行うプログラムの作成を行う。(CentOS7側)

php_info()を表示するデータを作成していきます。

```
cd ~/php_share/
mkdir php_program
vim php_program/index.php
```

index.phpを作成したら下記プログラムを書き込みます。

``` php:/home/user/php_share/index.php
<?php
phpinfo();
```

その後ファイルを保存し、Windows10のブラウザから `http://[CentOSのIP]/php/index.php`
にアクセスします。

無事php_infoが出力されればここまでは問題なく動作していると思います。
php_infoの表示例は[こちら](https://www.javadrive.jp/php/install/index6.html)を参照

### CakePHPのアプリを作成する。

次にCakePHPが動作するか確認を行います。

```
cd ~/php_share/
composer create-project --prefer-dist cakephp/app cakeapp
```

ここでCakePHPのアプリのひな型を作ってくれますが時間がかかりますので、
しばらく待ちましょう。
また途中で

```
Set Folder Permissions ? (Default to Y) [Y,n]? 
```

と聞かれたらYを入力すればよいです。

その後Windows10のブラウザから `http://[CentOSのIP]/cake`にアクセスし、
ページが表示されればOKです。
正しく表示される場合は色付きの綺麗なページが表示されます。

### PHPのインストール(Windows10側)
VS CodeにPHPのプラグインをインストールしていきますが、
VS CodeのPHPプラグインはPHP本体を必要とします。

ですので、Windows10側もPHPをインストールします。

chocolateyを使用している場合は、
管理者権限のコンソール画面から下記打ち込めばPHPがインストールできます。

```
choco install php
```

持っていない場合は [ここ](https://www.php.net/downloads.php)からダウンロードしてインストールしましょう。

### VS Codeの設定(Windows10側)
ここではインストール手順は省きますが、
ステップ実行に必要となるプラグインと便利なプラグインを追加します。

筆者は下記最低限必要そうなプラグインをインストールしました。

* PHP Debug
* PHP IntelliSense

またVS Codeの設定から下記設定が必要となります。

``` settings.json
"php.executablePath": "C:/tools/php73/php.exe"
```

### VS Codeのプロジェクトの設定を行う。(Windows10側)

CentOS7側で共有フォルダに作成したディレクトリをWindows10のVS Codeで開きます。
下図の赤枠を選択し、Windows側の共有フォルダ内にある `php_share/php_program` ディレクトリを開きます。

![0007.vscode02.png](https://qiita-image-store.s3.amazonaws.com/0/383232/50536435-ed34-708f-27a0-7d5919b96fe8.png)

それが終われば、VSコードのデバッグ設定を行います。
「デバッグウィンドウ」から「構成の追加」で「PHP」を選択します。
※画面はRailsの時のものですが、操作としては似ているので下記スクリーンショットを貼ってます。

![0008.vscode03.png](https://qiita-image-store.s3.amazonaws.com/0/383232/094bc47e-0b8b-d178-0341-602b695addc1.png)

基本的にプロジェクト毎の設定は各ディレクトリ毎の `.vscode/launch.json` に作成されます。
その後 `launch.json` を開いて下記のように修正します。

``` json:.vscode/launch.json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [{
      "name": "Listen for XDebug",
      "type": "php",
      "request": "launch",
      "port": 9000,
      "stopOnEntry": true,
      "pathMappings": {
        "/home/user/php_share/php_program": "${workspaceRoot}"
      }
    },
    {
      "name": "Launch currently open script",
      "type": "php",
      "request": "launch",
      "program": "${file}",
      "cwd": "${fileDirname}",
      "port": 9000
    }
  ]
}
```

これが終われば設定完了です。
次は実際にデバッグを行っていきます。
※正直なところポートを9000番と指定しているだけで、何故これでCentOS7側のXdebugに接続してくれるのか不明です。。。

### VS Codeからデバッグを行う。(Windows10側)

VS Codeの再起動を行い再度 `php_program` のフォルダをWindows側から選択し、
`F5キー` を入力してデバッグを開始します。
デバッグを開始するとVS Code下部のステータスバーがオレンジになります。

あとはindex.phpにブレークポイントを設定して ブラウザから `http://[CentOSのIP]/php/index.php` に接続するとブレークポイントの箇所でプログラムが止まります。

### CakePHPのアプリもデバッグを行ってみる。(Windows10側)

同じように上の方でCentOS7側から作ったCakePHPのアプリ `php_share\cakeapp`を
Windows10のVS Code 側から開いて、デバッグを設定を行います。
この辺りは `php_share\php_program` で開いた時と同じ設定を行います。
cakeapp用のlaunch.jsonは下記です。
※ `pathMappings` が変わったぐらいです。

``` json:.vscode/launch.json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [{
      "name": "Listen for XDebug",
      "type": "php",
      "request": "launch",
      "port": 9000,
      "stopOnEntry": true,
      "pathMappings": {
        "/home/user/php_share/cakeapp": "${workspaceRoot}"
      }
    },
    {
      "name": "Launch currently open script",
      "type": "php",
      "request": "launch",
      "program": "${file}",
      "cwd": "${fileDirname}",
      "port": 9000
    }
  ]
}
```

あとは `webroot/index.php` 辺りにブレークポイントを仕掛けて、
ブラウザから `http://[CentOSのIP]/cake/` に接続するとブレークポイントの箇所でプログラムが止まります。

何故かは不明ですが、

1. `webroot/index.php` の先頭にブレークポイントを張ってないのに止まったり
2. 例外が発生した個所で勝手にブレークポイントが止まったり、

しますが、理由は不明です。多分仕様かな？と思いますがブレークを仕掛けた箇所にちゃんと止まってくれたのであまり気にしていません。

これでCakePHPや単一のPHPプログラムのブレークポイントを仕掛ける部分までの設定が出来ました。

# お疲れさまでした。

以上開発環境構築方法でした。

もし何かしら間違いや誤りなどありましたらご指摘お願いします。
またコメントやこうしたら良いよみたいなアドバイスがあればコメントいただけると嬉しいです。

# 参考URL

* https://getcomposer.org/download/
* https://qiita.com/takmt/items/0858dbd3c53cabaa4395
* https://qiita.com/takmt/items/302ebdf05c0cfebf4547
* https://qiita.com/castaneai/items/d5fdf577a348012ed8af
* https://qiita.com/nao_tuboyaki/items/9615166e2374a565af80