XAMPPで複数バージョンのPHPを共存させたい

# XAMPPで複数のPHPは動作しないの？

PHPのバージョンアップが提供された際や古くなったPHPバージョンのプロジェクトを新バージョンで同じように動くかどうかをローカルで確認したい。

まぁVagrantを使ったりすればあっさり解決できるかもしれないが、私の環境ではXAMPPを利用していたり、複数の案件が同時進行していることが多い。

Qiita内では

- xamppで複数のバージョンのphpを切り替えて使いたい！！！
https://qiita.com/shie-works/items/65234ffb6753e277d621
- XAMPPで複数バージョンのPHPを切り替えてApache + MySQL を使う方法 on Windows
https://qiita.com/kaitaku/items/e0ae54fc04d222ded5c9

このような記事があるが、これでは稼働しているバージョンは1つに限定されるため、**「同時に起動して確認する」**という事ができず、他のプロジェクトも道連れになってしまうためによろしくない。

## つまり、やりたいことは

- 現状のプロジェクト達のPHPバージョンはそのまま（今回はPHP7.4とする）
- バーチャルホストとして特定のプロジェクトのみPHP8.0を使ってみたい

# CGIモードを使えばできそう

メインのPHPバージョン（PHP7.4）の環境はとりあえず変えたくないので、この状態をベースにする。
**＝ XAMPP 7.4.x をインストールした状態（モジュール版で動作）からスタートする**

# 注意
私の例はportable版になっているため、インストール版ではパスの設定が微妙に違う可能性がある。（ドライブレターが必要だったり？）

# 1. XAMPPのサイトから XAMPP 8.0.x をダウンロードし、解凍する

https://sourceforge.net/projects/xampp/files/

私はportable版を利用しているため、`xampp-portable-windows-x64-8.0.7-0-VS16.zip` をダウンロードした。

# 2. 解凍したphpフォルダの名前を変える

`path_to_download/xampp/php` → `path_to_download/xampp/php80` とする

# 3. `php80`フォルダを現行のxamppフォルダにコピー

`php` フォルダ（PHP7.4.xのもの）と `php80` フォルダ（コピーしたphp8.0.xのもの）同じ階層になるようにコピー

# 4. `xampp/php80/php.iniの編集`

```conf
# パスの修正

- include_path = \xampp\php\PEAR
+ include_path = \xampp\php80\PEAR
- extension_dir = "\xampp\php\ext"
+ extension_dir = "\xampp\php80\ext"
- error_log="\xampp\php\logs\php_error_log"
+ error_log="\xampp\php80\logs\php_error_log"
- browscap = "\xampp\php\extras\browscap.ini"
+ browscap = "\xampp\php80\extras\browscap.ini"
```

# 5. `xampp/apache/conf/httpd.confの編集` 

```conf
# コメントをはずす
- #LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
+ LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
```

# 6. `xampp/apache/conf/extra/httpd-xampp.confの編集`

```conf
# 以下を追記
ScriptAlias /php80/ "/xampp/php80/"
<Directory "/xampp/php80">
    AllowOverride None
    Options None
    Require all denied
    <Files "php-cgi.exe">
          Require all granted
    </Files>
</Directory>
```

# 7. `xampp/apache/conf/extra/httpd-vhosts.confの編集`

一番のキモになる部分。
UnsetEnv と FilesMatch部がCGIモードを利用することの宣言部分になる。

```conf
# 以下を追記
<VirtualHost *:80>
    DocumentRoot "/xampp/htdocs/php80test/public_html"
    ServerName php80.localhost.com
    ErrorLog "/xampp/htdocs/php80test/logs/error.log"
    CustomLog "/xampp/htdocs/php80test/logs/access.log" common
    UnsetEnv PHPRC
    <FilesMatch "\.(phtml|php)$">
        php_flag engine off
        SetHandler application/x-httpd-php80-cgi
        Action application/x-httpd-php80-cgi /php80/php-cgi.exe
    </FilesMatch>
</VirtualHost>
```

# 8. 7で設定したパスにindex.phpを設置

```xampp/htdocs/php80test/public_html/index.php
<?php phpinfo(); ?>
```

# 9. XAMPPを起動して確認

- http://php80.localhost.com へアクセスし
    - `PHP Version` が `8.0.7` になっていることを確認
    - `Server API` が `CGI/FastCGI` になっていることを確認
- https://localhost/dashboard/phpinfo.php へアクセスし
    - `PHP Version` が `7.0.x` のままであることを確認
    - `Server API` が `Apache 2.0 Handler` のままであることを確認


以上で設定は完了。
あとは No7のUnsetEnvとFilesMatch部をバーチャルホストごとに設定していけばそのホストはPHP8.0.xで動作するようになる。

これを応用すればいくつでもPHPバージョンを共存させることができるため、納品先サーバーのPHP環境ごとに設定していくのも良いかもしれない。

# 参考
Run multiple version of PHP in XAMPP Windows (Without installing multiple XAMPP)
https://themanish.com/run-multiple-version-of-php-in-xampp-windows-without-installing-multiple-xampp/

# あとがき

あくまでCGIモードで動作するため、モジュール版とは微妙に動作が異なる可能性があるので注意。
また、不具合が出た場合や、コマンドライン（Composer含む）が上手く動かない場合はこちらのトラブルシューティングも参照すると解決するかもしれない。

https://qiita.com/bananacoffee/items/7dc8ee260050f13be372