ドメインやディレクトリ別に異なるPHPバージョンを設定する方法

この間、一部のプログラムのみ別のPHPバージョンで動かしたいという案件がありました。
サイト全体をバージョンアップしてしまうと他のプログラムへの影響が懸念されるため、サイト全体のPHPバージョンは変えないというのが条件。

なので、作業対象のプログラムがあるサブディレクトリに対してのみphpのバージョンアップを行いたいところ。

調べてみると、.htaccessとphp.cgiファイルを使うことで実現できることが分かりました。
今回は、さくらインターネットとロリポップにおいて、実際に確認できた方法をまとめていきます。

特定のプログラムがあるサブディレクトリだけ最新のPHPバージョンを適用したい」というケースのほか、「プログラムやサイトデータの検証のため、PHPバージョンを変更したテスト用ディレクトリを設けてテストしたい」という状況でも便利な方法だと思うので、是非参考になればと思います。

設定方法

前提

例として、ルートや他のサブディレクトリでは従来のphp5.6のまま運用しつつ、zzzディレクトリ配下のみphp8.0を適用したい場合の設定内容を書いていきます。

最終的な構成は以下のイメージ。

/  … php5.6のまま使用
/xxx/  …ルートと同じ環境
/yyy/  …ルートと同じ環境
/zzz/  …php8.0にバージョンアップしたい環境
/zzz/php.cgi  …追加ファイル
/zzz/.htaccess  …追加ファイル

php.cgiファイルの作成

php.cgiという名前のファイルを作成し、下記コードを記述します。

#!/bin/sh
exec /usr/local/php/8.0/bin/php-cgi

*さくら・ロリポップ共通
*PHPバージョンのパスは2022/12/20執筆時点での情報です

現時点では、php8.0はさくら・ロリポップ共に上記パスで動作しました。
「/usr/local/php/8.0/bin/php-cgi」の部分はサーバーによるので、ほかのサーバーで使う時はそのサーバーのパスに合わせる必要があります。

.htaccessの用意

.htaccessファイルを作成し、下記コードを記述します。
php.cgiファイルのディレクトリパスを実際のものに置き換えて使ってください。

Action myphp-script /zzz/php.cgi
AddHandler myphp-script .php .html

*さくら・ロリポップ共通

php.cgiと.htaccessのアップロード

作成した2つのファイルをPHPバージョン切り替え対象のzzzディレクトリにアップロードした時点でPHPバージョンアップが適用されます。

実際にPHP8.0が適用されたかどうかはphpinfo()を記述したファイルを用意して確認してみましょう。

<?php phpinfo(); ?>

そのファイルをアップロードしてアクセスしてみてみます。

▼2ファイルアップロード前

▼アップロード後

無事PHP8.0と表示されたら成功です!

モジュール版とCGI版の違い

今回のことを調べるにあたり、これらの用語がよく出てきたので備忘録に。

  • CGI版
    →実行ファイル形式とも呼ばれる。Webサーバーとは別のプロセスで実行され、Webサーバー本体を動かすroot権限等のユーザーとは切り離されている。
    特長:セキュリティや安定性に優れている
  • モジュール版
    →Webサーバー本体を動かすroot権限等のユーザーで実行される。処理は高速だが、別ユーザーが作成したプログラム同士が干渉する可能性がある
    特長:処理が高速

使用サーバーがどちらのモードを使っているかは、phpinfo()の「Sever API」欄で確認できます。
モジュール版の場合「Apache 2.0 Handler」、CGI版は「CGI/FastCGI」と書いてあります。

それが今回のこととどんな関係があるのかというと、今回の方法でディレクトリ毎の環境を変えられるのはCGI版の特長らしいということを見かけたからです。

[CGI版] 通常.htaccessやphp.iniファイルを用いてディレクトリ毎に環境を変えることができる

CGI版PHPとモジュール版(スクリプト版)PHP

上述で動作を確認したのはCGI版だったので、「じゃあモジュール版のPHPだと今回の方法は使えないのかな?」という疑問が。
ロリポップの環境をPHP8.1モジュール版にして、同様の設定・方法でテストしてみました。

結果、問題なく特定ディレクトリだけのPHPバージョンの切り替えが成功しました

(補足…モジュール版へ変更後、phpinfo()の「Sever API」欄は「Apache 2.0 Handler」に。.htaccessとphp.cgiでバージョン切り替え後は「CGI/FastCGI」になったことを確認)

問題なく出来た理由はロリポップが特別に対応しているのか、ほかのサーバーのモジュール版でも問題なく使えるのかわかっていませんが、使いたい状況になったら試していこうと思います。

まとめ

今回の内容は、個人的に「知っていればもっといい提案ができたし、もっとスムーズに検証や改修を進められたのにな…」と思い返す案件がいくつもあるようなトピックでした。

ちなみに、PHPバージョン切り替えを行なったディレクトリにアクセスした際に「500 internal server error」は表示された場合、各ファイルのパーミッションが正しくない場合があります。
その際は各レンタルサーバーの指示に従って設定しましょう。