WSL2+PhpstormでPHP開発(docker なし、複数PHP)

環境構築

この投稿の通りに WSL2 上に Docker を利用してコンテナーで Apache を動かした時、xdebug を使用するとものすごく遅くなってしまって、仕事に使い物にならなかったです。

xdebug はできる限りに使いたかったため工夫してみたところ、Apache は WSL2 上で直接動かして、そのほかは Docker コンテナー上で動かしてみようと思いました。しかし、一つの環境の中で複数の PHP バージョンを動かす必要があり、いろいろ調べた結果、Apache の vhost ごとに PHP バージョンを指定できる方法を見つけました。

本投稿は、WSL2 上で 複数の PHP バージョンを Apache の vhost ごとに動作する設定をメモしたものです。ほぼ以下の英語の記事の手順を従っています。

WSL2 に Apache をインストールする

$ sudo apt update
$ # Apacheと必要なモジュールをインストール
$ sudo apt install -y apache2 libapache2-mod-fcgid
$ apache2 -v # Apache バージョンの確認

WSL2 に php-fpm をインストールする

$ # レポジトリを管理するUbuntuのパッケージPPA
$ sudo apt install -y software-properties-common
$ sudo add-apt-repository ppa:ondrej/php # PHP PPA Repositoryを追加
$ sudo apt-get update
$ sudo apt install -y php5.6-fpm # PHP 5.6をインストール
$ sudo apt install -y php7.2-fpm # PHP 7.2をインストール
$ sudo apt install -y php8.0-fpm # PHP 8.0をインストール

複数の PHP バージョンのコマンドを実行するために設定する

update-alternatives コマンドをつかって、PHP バージョンを切り替えることができます。

$ update-alternatives --list php # 利用できる PHP バージョンの確認
/usr/bin/php5.6
/usr/bin/php7.2
/usr/bin/php8.0
$ sudo update-alternatives --config php # PHP バージョンの切り替え
There are 3 choices for the alternative php (providing /usr/bin/php).

  Selection    Path             Priority   Status
------------------------------------------------------------
* 0            /usr/bin/php8.0   80        auto mode
  1            /usr/bin/php5.6   56        manual mode
  2            /usr/bin/php7.2   72        manual mode
  3            /usr/bin/php8.0   80        manual mode

Press <enter> to keep the current choice[*], or type selection number:

複数の PHP バージョンで Apache を構成する

必要な Apache モジュールを有効にする

FPMおよびFastCGIをApacheサーバーと統合するために実行する必要があるようです。

$ sudo a2enmod actions fcgid alias proxy_fcgi # Apache モジュールを有効化

Apache の vhost の設定を行う

PHP 5.6 用サンプル

$ sudo mkdir /var/www/php56 # サンプルページのドキュメントルートを作成
$ echo "<?php phpinfo(); ?>" | sudo tee /var/www/php56/index.php # サンプルページを作成
$ sudo vi /etc/apache2/sites-available/php56.example.com.conf # vhostの設定
<VirtualHost *:80>
    ServerName php56.example.com
    DocumentRoot /var/www/php56
    ErrorLog ${APACHE_LOG_DIR}/php56-error.log
    CustomLog ${APACHE_LOG_DIR}/php56-access.log combined
    <FilesMatch \.php$>
        # Apache 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php5.6-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</VirtualHost>
$ sudo a2ensite php56.example.com # サンプルを有効にする。

PHP 7.2 用サンプル

$ sudo mkdir /var/www/php72
$ echo "<?php phpinfo(); ?>" | sudo tee /var/www/php72/index.php
$ sudo vi /etc/apache2/sites-available/php72.example.com.conf
<VirtualHost *:80>
    ServerName php72.example.com
    DocumentRoot /var/www/php72
    ErrorLog ${APACHE_LOG_DIR}/php72-error.log
    CustomLog ${APACHE_LOG_DIR}/php72-access.log combined
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</VirtualHost>
$ sudo a2ensite php72.example.com

PHP 8.0 用サンプル

$ sudo mkdir /var/www/php80
$ echo "<?php phpinfo(); ?>" | sudo tee /var/www/php80/index.php
$ sudo vi /etc/apache2/sites-available/php80.example.com.conf
<VirtualHost *:80>
    ServerName php80.example.com
    DocumentRoot /var/www/php80
    ErrorLog ${APACHE_LOG_DIR}/php80-error.log
    CustomLog ${APACHE_LOG_DIR}/php80-access.log combined
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php8.0-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</VirtualHost>
$ sudo a2ensite php80.example.com

Apache と php-fpm を起動する

$ sudo service apache2 start
$ sudo service php5.6-fpm start
$ sudo service php7.2-fpm start
$ sudo service php8.0-fpm start

WSL2に接続できるように Windows の hosts を設定する

C:\Windows\System32\drivers\etc\hosts ファイルをメモ帳などで開いて以下の設定を追記します。

127.0.0.1 php56.example.com
::1       php56.example.com
127.0.0.1 php72.example.com
::1       php72.example.com
127.0.0.1 php80.example.com
::1       php80.example.com

Xdebug をインストールする

各々の PHP バージョンンに対して xdebug をインストールします。

$ sudo apt install -y php-pear
$ pecl install xdebug
$ sudo apt install php5.6-xdebug
$ sudo apt install php7.2-xdebug
$ sudo apt install php8.0-xdebug

とりあえず php8.0-fpmに対して xdebug の設定を行います。

$ sudo vi /etc/php/8.0/fpm/php.ini
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_port = 9003
xdebug.idekey = PHPSTORM
xdebug.log = /tmp/php8.0-fpm-xdebug.log

xdebug.client_host = 《WSL2のホストIPアドレス》 も設定する必要がありますが、動的に変わる値(?)のため、WSL2 を起動する時に自動的に設定するようにします。

PHP をコマンドで実行する時のためには、cli 用 php.ini に xdebug の設定を行う必要があります。

$ sudo vi /etc/php/8.0/cli/php.ini
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_port = 9003
xdebug.idekey = PHPSTORM
xdebug.log = /tmp/php8.0-cli-xdebug.log

ただし、WSL2では /etc/rc.local などを起動時に実行することはできないようです。しかし、起動時に /sbin/mount -a コマンドが呼び出されるため、これをフックする方法を利用して実現できます。以下はそのための設定です。

fstab はマウントするファイルシステムの情報を記述するファイルであり、再起動もしくは mount -a を実行する際に設定が反映されるようです。

$ echo 'none none rc defaults 0 0' | sudo tee -a /etc/fstab
$ sudo chmod +x /sbin/mount.rc
$ sudo vi /sbin/mount.rc
#!/bin/bash

sed -i -e '/xdebug.client_host/d' /etc/php/8.0/fpm/php.ini
echo -n 'xdebug.client_host = ' >> /etc/php/8.0/fpm/php.ini
echo `awk '/nameserver/ {print $2}' /etc/resolv.conf` >> /etc/php/8.0/fpm/php.ini

sed -i -e '/xdebug.client_host/d' /etc/php/8.0/cli/php.ini
echo -n 'xdebug.client_host = ' >> /etc/php/8.0/cli/php.ini
echo `awk '/nameserver/ {print $2}' /etc/resolv.conf` >> /etc/php/8.0/cli/php.ini

service apache2 start
service php5.6-fpm start
service php7.2-fpm start
service php8.0-fpm start

下の4行は、WSL2 を起動する際に自動的に Apache2 と php-fpm が起動されるように追加します。

ブラウザーで確認する

http://php80.example.com に接続し、PhpStorm設定で必要な情報も一緒に確認しておきます。
また、上のようにXdebugが設定されていることを確認します。

PhpStorm の Xdebug 設定を行う

※Laravel を動かす時の注意点

Windows の hosts を設定する時

Windows の hosts を設定する時、127.0.0.1の代わりにlocalhostと設定しないと接続しない。Apache の Listen のポートに対して、IPv4 と IPv6 の関連でブラウザーや Postman からうまく接続できないです。そのため、Apache の設定を変える必要があります。以下は、Laravel に接続するための例です。(WSL2 上の Apache の ports.conf、vhost、Winsows のhosts 順番)

Listen 127.0.0.1:80
Listen [::1]:80

<IfModule ssl_module>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>
<VirtualHost *:80>
    ServerName laravel.sample.com
    ServerAlias laravel.sample.com
    DocumentRoot /home/user/project_path/public
    ErrorLog ${APACHE_LOG_DIR}/laravel-error.log
    CustomLog ${APACHE_LOG_DIR}/laravel-access.log combined
    Options Indexes FollowSymLinks
    <Directory "/home/user/project_path/public/">
        AllowOverride All
        Require all granted
    </Directory>
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php8.0-fpm.sock|fcgi://localhost/"
    </FilesMatch>
</VirtualHost>
127.0.0.1 laravel.sample.com
::1       laravel.sample.com

Laradoc などコマンド実行時は Docker を利用している場合

php artisan optimize を実行する際にルートパスを設定しているため、プロヘクト配置場所に対して Docker 内のパスと WSL2 内のパスが一致する必要があります。WSL2 でシンボリックリンクなどを利用して解決できます。

例えば、docker-compose で /home/user/project_path/:/var/www/src のようにマウントしているのであれば、以下のようにシンボリックリンクを作成します。

$ ln -s /home/user/project_path /var/www/src

WSL2 上でファイルのアクセスを確認

Apache が Laravel のソースコードを実行できるように所有権とアクセス権限を以下のように変更します。

$ chown -R user:www-data /home/user/project_path/*
$ chmod -R g+w /home/user/project_path/*

Laravel で必須の Apache モジュールを有効にする

mod_rewriteが利用可能ではなければ、Laravel は動きません。

$ cat /etc/apache2/mods-available/rewrite.load # モジュールがあるか確認する
$ sudo a2enmod rewrite # モジュールを起動
$ sudo service apache2 restart # Apache の再起動

結果的に構築された構成をまとめた図

ログ書き込みでパーミッションエラーになる時

WSL2 で利用しているユーザーを Apache グループに追加して、Apache でログを書いても、コマンド実行する時ログを書いても問題ないようにします。

$ groups 《ユーザー名》 # ユーザーが属しているグループを確認する。
《ユーザー名》 : 《ユーザー名》
$ sudo usermod -g www-data 《ユーザー名》 # ユーザーを www-dataグループに追加する。
$ groups 《ユーザー名》
《ユーザー名》 : www-data

※参考

関連記事

コメント

この記事へのコメントはありません。

カテゴリー

お問い合わせはコチラ!