PHP5のサーバからPHP8のサーバへ移行する際に確認した箇所
OSのサポート切れに伴うサーバの移行
CentOS7のサポートが2024年6月で切れることに伴い、OSと共にPHPのバージョンも最新の8に移行した。 その際に修正、確認したところを備忘録も兼ねてメモ。
SELINUX等のOS設定、.htaccess、httpd.conf、及びPHPのモジュールとphp.iniの記述
基本的すぎる箇所だと思うが、案外ここが新旧揃って合っていないことがエラーやトラブルの原因になりやすい。
まずSELINUXが旧でオフになっていないか(なっている場合、その理由は?)、時刻設定やDNS設定などを確認し、Webサーバを立ち上げる前に一致させておきたい。
勿論、各種権限や、ログファイル等の出力先や、ディレクトリの書き込みの権限もチェック。ここが正しくないとすぐにエラーになる。
旧サーバから各種「.htaccess」「httpd.conf」「php.ini」をバックアップし、これをできるだけ新サーバでも同じ設定で運用できるかの確認は基本となる。
特に「.htaccess」は隠しファイルなので、旧サーバからごっそりファイルを持ってきたつもりが、移行できなかった、という場合もあるので、注意。
「.htaccess」のエラーはログにも出ないで503になることもあるので調査に時間がかかる。
Amazon Linux等に移行して、php-fpmにしている場合は、 php_value や php_flagの設定が使えなくなるので、ここも注意が必要。
最終的にphpの設定に関しては、新サーバの初期設定を行い閲覧できるようになったら直ちにphpinfo()で新旧比較をして、一つ一つ差異を一致させていくのが遠回りだが、一番確実だろう。
(勿論、旧サーバが動くことが大前提だが……)
その際にインストールされてないphpのモジュールも見つかる筈。
すでにphp8で使われてないモジュールがある場合が一番厄介だが、ネットで代替手段を一つずる見つけて行くしかない。
セキュリティ的な問題がない限り、そこまで廃止されているモジュールはない筈だが、PEAR系は廃止されている(mysql_*系の関数がなくなったため)なので、
DBアクセスにPEAR系を用いている場合はPDOに置き換えるしかない。
廃止された関数の使用
ApacheやPHPの設定が新旧で同じになった場合、後はPHP5からPHP8でできなくなった事を修正していくことになる。
まず、php8で廃止された関数の置き換えであるが、これは比較的容易な部類だろう。
エラーログにも使っている箇所があれば分かりやすく吐き出されるし、廃止された関数を事前に調べてgrep等で検索すれば良い。
主な廃止関数は以下。
create_function→無名関数へ置き換え split関数→explode関数に置き換え ereg系関数→preg系関数に置き換え each()→foreach に置き換え ほかにもあるが、今ではchatgptに聞けば書き換え手段も含めて、丁寧に教えてくれるだろう。
ほかにもあるが、今ではchatgptに聞けば書き換え手段も含めて、丁寧に教えてくれるだろう。
コンストラクタの定義方法
特にphp5系で動いていた古いライブラリを使用している場合に注意が必要な項目である。
PHP5だと、クラス名と同じ名前のメソッドをコンストラクタとして使用していたが、 php8ではこの形式は完全に廃止となり、「__construct」を使用しなければならない。
・廃止された書き方
class oldclass { function oldclass() { echo "This is construct"; } }
・「__construct」を使用した書き方
class oldclass { function __construct() { echo "This is construct"; } }
単にクラス名と同じ名前を使用しているfunctionを「__construct」に置き換えるだけなので、書き換え自体は容易だが、php5系のライブラリでphp8対応のバージョンが出ていなかったり、古いバージョンのままで使いたい理由があったりすると、 おそらくほぼ古い書き方をしているので、自力で置き換える必要がある。
型の宣言や型チェックの厳格化
ここが一番引っかかる箇所が多いと思われる。
php8では変数や配列にアクセスする際、既に宣言がされているか、使用されている型は何かというチェックが厳しくなっている。
php固有のファンクションにおいても、php5以前に比べ、引数に渡す変数には、配列を渡すべきところは配列を、オブジェクトであるべきところはオブジェクトを渡さなければエラーになる。
javaやを使っている人には当たり前のことのように思えるだろうが、php5はここが非常に緩かったため、その意識でコーディングしていた場合、php8に移す場合は、修正に大変時間がかかることになるだろう。
一番大きいのはCount関数の挙動だろう。
例えば、以下のような処理を書いたとき、Count内の変数$arrayに間違いなく配列が入ってくる処理になっているだろうか。
for($i=0;$i<=count($array); $i++) { $int = $i; }
php8より前だとcount($array)でwarningは出るが、致命的なエラーではないため、ループが一回は通る。 なので、$arrayが配列ならば1以上の数字が、配列で無いならば、$iは0が……という処理ができていたが、 php8以降は$arrayが配列でなければ、致命的なエラーで落ちる。 countは配列の要素を数えるので当たり前といえば当たり前だが、古いphpではこれが通っていた。
同じように、array_key_exists() も以前は配列で無くオブジェクトを渡しても、trueを返したが、php8では配列で無ければ落ちる。あくまで配列の要素をチェックする関数だからだ。 これらの関数は未使用になったわけではないので、エラーが起きる使い方をしていないかどうかは、実際にテストをしてチェックするしかない。 他にもmb_strrpos 関数やimplode関数は処理が変わっているので注意が必要だ。
こうした変更は、javaのように変数を宣言した時点でどんな型にするかを宣言していれば大きな問題にはならないのだが、 phpはその辺が緩く、特にif文やループ文の中で初めて変数や配列を宣言するなんて処理をしていると、上記の変更にひっかかって地獄になりやすい。 修正に関しては、一つ一つの処理を厳密にチェックしていくしかもはや対処法は無いが、 これを機にphpであっても変数や配列にセットする型や値の宣言は厳密にするよう、処理を見直すと良いだろう。
おしらせ
電巧社ではセキュリティ分野専門のブログも公開しています。ゼロトラストセキュリティを始めとした、ランサムウェアへの対処法等を紹介しています。こちらもよろしくお願いします。