結論から書くと、PHP のバージョンを切り替えてシステムが動かなくなったら、原因を調べる前に、まず元のバージョンに戻します。業務を止めないことが先で、原因の調査は、エラーの記録を取ってから検証環境で行います。本番で設定やコードを直しながら原因を探すと、どの変更が効いたのか分からなくなり、別の問題を増やしがちです。
原因は、大きく次の4つに分けて考えると切り分けやすくなります。
- 新しい PHP で削除された関数や、変わった動き
- 拡張モジュールが有効になっていない
- PHP の設定が新しいバージョンに引き継がれていない
- フレームワークやライブラリが新しい PHP に対応していない
最初にやること: 記録して、元に戻す
慌てて戻す前に、次のことを短時間で記録します。
- 切り替えた日時と、切り替えた対象(サーバー全体か、特定のディレクトリか)
- 切り替える前と後のバージョン
- 症状(どの画面で、何が表示されたか)。画面のスクリーンショットも残す
- エラーログの場所と、その時点のログのコピー
そのうえで、管理画面で元のバージョンに戻し、主な画面が元どおり動くことを確かめます。サーバーによっては、管理画面ではなく .htaccess の記述でバージョンを指定している場合もあります。その場合は、切り替えのときに変えた行を元に戻します。
元のバージョンがすでに提供されていない、または提供の終了日が迫っている場合は、戻せません。その場合は、業務への影響が大きい画面から最小限の修正をすることになります。直す前にファイルとデータベースのバックアップを取り、何をいつ変えたかを記録してください。古い PHP を使い続けることのリスクと優先順位は「サポート切れ PHP を放置するリスクと、対応の優先順位」で説明しています。
症状から当たりをつける
エラーログを見る前でも、症状からある程度は当たりがつきます。
| 症状 | 考えられる原因 | 次に見るもの |
|---|---|---|
| 画面が真っ白になる | 致命的なエラーで処理が止まり、エラーの表示が無効になっている | エラーログ |
| サイト全体が 500 エラーになる | .htaccess の PHP 設定の書き方が、今の動作方式で使えない |
サーバーのエラーログ、.htaccess |
| 一部の画面だけエラーになる | 削除された関数や、変わった動きを使っている | エラーログのファイル名と行番号 |
| データベースに接続できない | 古い接続用の関数を使っている、接続のエラーの扱いが変わった | 接続処理のコード |
| 文字化けする | 文字コードの設定が引き継がれていない | 新旧の PHP の設定の比較 |
| 「Deprecated」の表示が大量に出る | 非推奨になった書き方を使っている。エラーが画面に表示される設定になっている | エラーの表示の設定 |
| メール送信や画像の処理だけ失敗する | 必要な拡張モジュールが有効になっていない | 有効な拡張モジュールの一覧 |
500 エラーについて補足します。PHP のマニュアルのとおり、.htaccess の php_value などで PHP の設定を変えられるのは、PHP を Apache のモジュールとして動かしている場合です。CGI や FastCGI で動かしている場合は、ディレクトリごとの設定に .user.ini を使います。バージョンの切り替えで動作の方式も変わるサーバーでは、.htaccess の同じ行がエラーの原因になり得ます。
エラーログを見る
切り分けの中心はエラーログです。サーバーの管理画面にエラーログを見る機能があればそれを使い、無ければ PHP の設定でログの出力先を決めます。
; .user.ini の例(CGI・FastCGI で動かしている場合)
log_errors = On
error_log = /home/ユーザー名/logs/php_error.log
display_errors = Off
ログの出力先は、公開ディレクトリの外にします。PHP のマニュアルでは、display_errors は開発のための機能で、インターネットにつながった本番では使わないよう明記されており、本番ではエラーの表示ではなくログへの記録を強く勧めています。原因を探すために本番でエラーを画面に表示すると、ファイルのパスや設定の内容を利用者に見せることになります。
ログに出るメッセージから、原因を絞り込めます。
Call to undefined function mysql_connect()—mysql拡張は PHP 7.0 で削除されました。mysqliか PDO への書き換えが必要です。Call to undefined function each()やcreate_function()— どちらも PHP 8.0 で削除されました。Passing null to parameterで始まる Deprecated — PHP 8.1 で非推奨になった、組み込み関数の引数への null の受け渡しです。- 動的プロパティの作成についての Deprecated — PHP 8.2 で非推奨になりました。
Deprecated は、今はまだ動くという意味です。処理を途中で止めるのは Fatal error のほうなので、そちらから見ます。
検証環境で、原因ごとに直す
本番を元に戻したら、検証環境で直します。順番は次のとおりです。
- 新しいバージョンと同じ PHP で、本番のコピーを動かす。 ファイルとデータベースのコピーを使い、本番と同じ設定にします。
- 新旧の PHP の設定を比べる。 本番で、古いバージョンと新しいバージョンのそれぞれで
phpinfo()の出力を保存し、文字コード、タイムゾーン、アップロードの上限、有効な拡張モジュールを見比べます。確認用のファイルは、保存したらすぐに削除します。 - Fatal error から直す。 削除された関数の書き換えなど、処理が止まるものが先です。
- ライブラリとフレームワークの対応を確かめる。 Composer を使っていれば、
composer prohibits php 8.3のように、移行先の PHP への更新を妨げているパッケージを一覧にできます。 - 警告と非推奨を直す。 動くようになったら、ログに残る警告を減らします。警告が大量に残ると、本当のエラーが埋もれます。
移行ガイドは PHP のマニュアルにバージョンごとにあります。何世代も上げる場合は、間のすべてのバージョンのガイドを確認します。
参考までに、h-system が PHP 7 系から 8 系へ上げた業務システムでは、期間は数週間でした。使っている関数やライブラリ、テストの有無で大きく変わるため、あくまで一例です。
次に切り替えるときに確かめておくこと
もう一度切り替える前に、次のことを確かめておくと、同じことが起きにくくなります。
- コマンドラインの PHP も確かめる。 管理画面で Web の PHP を切り替えても、定期処理(cron)が使うコマンドラインの PHP は別のバージョンのままのことがあります。切り替えの後は、定期処理の結果も確認します。
- 切り替える単位を小さくする。 ディレクトリごとに切り替えられるサーバーなら、影響の小さいところから試します。
- 業務への影響が小さい時間に切り替える。 戻す手順と、確認する画面の一覧を先に用意しておきます。
- 提供元の予定を確認する。 古いバージョンの提供終了の予定日が分かっていれば、それを期限にして計画を立てます。
h-system でできること
h-system では、レンタルサーバーで動いている PHP のシステムについて、バージョンを切り替えたら動かなくなった場合の切り分けと修正、計画的なバージョンアップを開発者本人がお引き受けしています。本番を元に戻した状態でお問い合わせいただければ、ソースコードとエラーログを確認し、何を直せば新しいバージョンで動くかを調べてご報告します。初回のご相談と概算のお見積りは無料で、詳細な調査は有償です。範囲と費用は着手前にご案内します。