サーバーのPHPバージョンがPHP5.xからPHP8.xに変更となり動作エラーを修正した記録

PHP
この記事は約7分で読めます。

この記事は、1年11ヶ月前に書かれました。

はじめに

さくらサーバーなどの一般的なレンタルサーバーの場合、PHPバージョンアップはサーバー会社側にて定期的におこなってくれて非常に楽です。
しかし、古い案件の場合、PHP5.x時代に作成したプログラムが動いていたりします。PHP8.xにバージョンアップされた場合、動作不具合が発生します。先日、かなり前に担当したクライアントから、プログラムが動作しないと連絡がありました。
調査したところ、使用しているサーバー会社がPHP8.xにバージョンアップしたようだと判明。
その際に私が対処した主なエラーを備忘録として記録しておきます。

環境

  • PHP8.x
  • Apache
  • FreeBSD

PHPはフレームワークを使用していない状態となります。
いわゆるバニラPHPです。

エラー表示レベルの事前準備

PHPにはエラーレベル表示の設定があります。
一旦全てのエラーを表示させ、ひとつずつエラー潰しをしていきますので、以下の設定にしておきます。E_ALLは全てのエラーを表示するという意味になります。また、display_errosについては、ブラウザ上にエラーメッセージを表示するかの設定になります。いちいちApacheのエラーログを確認するのは面倒なので、ブラウザ上に表示されるように設定変更しておきます。通常運用ではオフが安全です。

error_reporting (E_ALL);
ini_set('display_errors', "On");

Warning: Undefined array key~の解決方法

PHP8にアップデートしてよく目にするのがこのエラーです。
「Undefined array key」は配列の中に存在しないキーを指定して何等かの処理をおこなおうとした時に発生します。このエラーはWarningに分類されています。
例えば、PSOTで受け取った値を処理する際に、以下のような処理をおこなった場合に「Undefined array key」が発生します。
”tel”のキーが配列内には存在しないにもかかわらず、printで処理しようとしています。

$post = array(
'name'=>'お名前太郎', 
'kana'=>'おなまえたろう', 
'email'=>'example@example.com' 
);

print $post['tel']; //telというkeyは配列に存在しない

では、どのように対処すればよいかというと、以下のようになります。
array_key_exists()は、配列の中に該当するキーが存在するかをチェックする関数です。まずはキーが存在するかを確認し、trueであれば処理をおこなうようにします。

if(array_key_exists('tel', $post)){
	print $post['tel']; 
}

Warning: Trying to access array offset on value of type null の解決方法

次によく発生するのがこちらのエラーです。PHP7.4からこのエラーはスルーしてくれません。
配列ではない変数を配列のように扱おうとすると発生するエラーです。「~of type int in」や「~of type bool in 」のパターンもあります。
以下のような場合にエラーが発生します。関数に配列ではなく数値を渡しています。

public function getdata ( $var = null ){
	foreach ( $var as $val ){
		//処理
	}
}

getdata(1) //関数に1を渡す

あらかじめ、配列であるかどうかを確認してから配列としての処理を実行すればエラーは発生しません。

public function getdata ( $var = null ){
	if ( is_array( $var ) ) {
		foreach ( $var as $val ){
			//配列であった時の処理
		}
	}else{
		//配列でない時の処理
	}
}

Warning: Undefined variable~の解決方法

こちらは、変数が定義されていない場合に発生するエラーです。
エラーが発生する簡単な事例としては以下になります。

$this['default'] = $default;

$defualtの変数は未定義のため「Undefined variable」エラーが発生します。
そこで、以下のように修正します。事前に変数を定義しておきます。

$default = [];
$this['default'] = $default;

もしくは、isset関数で変数の存在を確認することでエラーが解消します。

if (isset($default)) {
	$this['default'] = $default;
}

Fatal error: Uncaught Error: Call to undefined function get_magic_quotes_gpc()の解決方法

get_magic_quotes_gpcはかなり懐かしい関数なのですが、PHP8以降では削除となりました。例えば以下のように使用されているのをよく見かけます。

if (!get_magic_quotes_gpc()) {
   $name = addslashes($_POST['name']);
} else {
   $name = $_POST['name'];
}

対応策としては、get_magic_quotes_gpc()の行をまるごと削除で構いません。結果的には以下のように対応すればエラーは解消します。

$name = $_POST['name'];

マジッククォートとは、POSTやGETで受け取ったリクエストデータに入っているシングルクオート(’)やダブルクオート(”)、バックスラッシュ(\)などの文字をPHP側で自動的にバックスラッシュでエスケープしてくれる機能です。その機能がONかOFFかを判定する関数がget_magic_quotes_gpc()です。PHP4~PHP5時代はこの機能がONとなっているサーバーが多かったようです。SQLインジェクション対策で実装されていたようですが、この手の対策は自前で実装しているので、私はいつもOFFが前提でプログラムを作成していました。

PHP: get_magic_quotes_gpc - Manual

Deprecated: Function strftime() is deprecated in~の解決方法

strftime()関数はPHP8.1より非推奨となりました。Deprecatedは非推奨という意味となりますので、現時点では使用できますが、いずれ消えゆく関数ということなので、今のうちに対処しておいたほうがいいです。
以下のような例の場合、エラーが発生します。

setlocale(LC_TIME, 'ja_JP.UTF-8');
$row['date'] = strftime("%m月%d日", strtotime($row['date']));

date()関数に置き換えることでエラーが解消します。

//日付整形
setlocale(LC_TIME, 'ja_JP.UTF-8');
$row['date'] = date("m月d日", strtotime($row['date']));

まとめ

PHP5.xで動作しているサーバーがまだ多数存在しています。
サーバー会社からのアナウンスを見落としていると、ある日突然エラーで動かないとクライアントから連絡がくるかもしれません。
いずれのエラーも難しい対処ではないため、ひとつひとつ確実にエラーを消していけばクリアできます。
フレームワークを使用している場合は、フレームワークのドキュメントを参照してください。
私はバニラPHPでのスクラッチ開発が多いため、エラー修正についても全体の構成を把握しているため、特に問題なく作業を進められますが、フレームワークが絡んできますとかなりややこしいかと思います。
Lravel4からLaravel7にアップデートなど、骨の折れる作業のようです。