長らくPHPのバージョンを更新しないでいたのですが、かなり久しぶりに確認してみたところ、いまだに7.4.33のままでした。既に非推奨になっています。
仕事で触っているサーバやサイトは、PHPに限らず、なるべく新しいものがリリースされてから早いうちにアップデートしていくように心がけているのですが、その分、自分個人のサイトが疎かになっていました。反省です。
さて、非推奨のバージョンをそのまま使用し続けるのはリスクが伴うので、サーバ側で対応している最新版の8.3.7に変更したのですが…Google Analyticsと併用しているMogura Plus Xというアクセス集計・解析ツールがエラー続出となってしまったので、これを解決した手順をメモメモ。
大雑把にエラー内容
今回はPHP7.4.33から8.3.7へ変更したのですが、この間に、いくつか非推奨になったり削除になったものがありました。そのうち、Mogura Plus Xで引っかかったものが以下の通り。
Deprecated(廃止予定になった)
preg_match()の引数にnullは非推奨
trim()の引数にnullは非推奨
Deleted(削除された)
staticではないメソッドの呼び出し
get_magic_quotes_gpc()
each()
廃止予定:preg_match()のnull引数
まず最初に、Mogura Plus Xの管理画面に入ってすぐ目についたのが、以下の警告。
Deprecated: preg_match(): Passing null to parameter #2 ($subject) of type string is deprecated in [MoguraPlusXのインストール先]/inc/load_setting.php on line 64
Deprecated: preg_match(): Passing null to parameter #2 ($subject) of type string is deprecated in [MoguraPlusXのインストール先]/inc/load_setting.php on line 65
preg_match()の2番目の引数にnullを渡すことは非推奨で、今後廃止予定ですよ、という警告。調べてみると、nullを渡すことはPHP8.1系から非推奨になったようです。
ビルドイン関数(この場合、preg_match)のパラメータにおいて、デフォルトでnullableではなくなるそうで、引数にnullを使用したい場合は、nullableと明示的にマークする必要があります。
実際に load_setting.php の64~65行目とその前後の処理を見てみると…。
62: $_GET['ym'] = (isset($_GET['ym']) ? $_GET['ym'] : null);
63: $_GET['d'] = (isset($_GET['d']) ? $_GET['d'] : null);
64: $ym = (preg_match('/^[0-9]{6}$/',$_GET['ym']) ? $_GET['ym'] : gmdate('Ym', time()+constant('W3A_TIME_DIFF')*3600));
65: $d = (preg_match('/^[0-9]{2}$/',$_GET['d']) ? $_GET['d'] : gmdate('d', time()+constant('W3A_TIME_DIFF')*3600));
となっていました。
62~63行目で、条件に合致しない場合にnullをセットしていて、64~65行目でその変数をpreg_match()で判定しているので、ここの処理を書き換えれば良さそうです。
preg_match()をnullableにしてもいいかと思いますが、nullをセットしないよう修正します。
62: $_GET['ym'] = (isset($_GET['ym']) ? $_GET['ym'] : '');
63: $_GET['d'] = (isset($_GET['d']) ? $_GET['d'] : '');
これで、ひとつめの問題が解決しました。
廃止予定:trim()のnull引数
こちらも管理画面で表示されていた警告です。Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in [MoguraPlusXのインストール先]/plugin/raw_log.php on line 143
ひとつ上の「廃止予定:preg_match()のnull引数」と同じ警告ですね。raw_log.php の143行目とその前後の処理を見てみると…。
143: if(trim($v['ref'])){
144: if($v['ref_q']) $v['ref'] .= "?".$v['ref_q'];
145: $v['ref'] = setValueColor('ref',$v['ref'], $v['ref']);
146: echo '<tr><th class="no_th" width="100">Referer:</th><td> '.$v['ref'].'</td></tr>';
147: }
ここのif()で判定している$v['ref']にnullが入ってくることがあるようで、trim()もデフォルトでnullableではなくなることでの警告が出ている、ということですね。
先ほどのように、nullではなく空文字をセットするように変更してもいいですが、ここではis_null()で対処してみました。
143: if(!is_null($v['ref']) && trim($v['ref'])){
前後にもtrim()している箇所がいくつかありますので、同様にis_null()で判定しておいた方がいいかも。
以上で、管理画面のエラー表示はなくなりました。これでOK!…かと思いきや、PHP8.3.7に変更した直後から、アクセスログが取得できていません。アクセスログ取得処理でも問題が発生しているようです。
廃止済:非staticメソッドの呼出
設置が一番簡単で、情報がたくさん取得できる画像タグ設置タイプでアクセスログを取得しているので、その画像URLを直接ブラウザで表示してみました。すると、以下のようなエラーが。
Fatal error: Uncaught Error: Non-static method W3A_OutputLog::check_err() cannot be called statically in [MoguraPlusXのインストール先]/writelog.php:863
Stack trace: #0 [MoguraPlusXのインストール先]/index.php(2): include_once()
#1 {main} thrown in [MoguraPlusXのインストール先]/writelog.php on line 863
Fatal errorなので、処理を継続できない致命的なエラーです。
内容としては、W3A_OutputLogというクラスのcheck_err()をstaticで呼び出そうとしているのですが、そのメソッドはstaticではないので呼び出せず、これ以上処理が続けられませんよ、というエラー。
staticで呼び出したいなら、staticと明示すべし。writelog.phpを開くと、863行目以外にもたくさんstaticで呼び出そうとしている箇所があります。その全てのメソッドが非staticなので、staticにしてあげれば動きます。
例えば、863行目で呼び出そうとしているW3A_OutputLog::check_err()は31行目から記述されていますが、31行目を
31: static function check_err($db){
というように、functionの前にstaticを追記してあげればOK。
修正し、再度画像URLを直接表示してみると…別のエラーが発生しました。
廃止済:get_magic_quotes_gpc()
次に表示されたエラーは…。
Fatal error: Uncaught Error: Call to undefined function get_magic_quotes_gpc() in [MoguraPlusXのインストール先]/writelog.php:16
Stack trace: #0 [MoguraPlusXのインストール先]/writelog.php(384): W3A_OutputLog::quote_smart('Mozilla/5.0 (Wi...', 'STR')
#1 [MoguraPlusXのインストール先]/writelog.php(865): W3A_OutputLog::createlog(Object(w3a_db_mysql), 'img', false)
#2 [MoguraPlusXのインストール先]/index.php(2): include_once('/home/...')
#3 {main} thrown in [MoguraPlusXのインストール先]/writelog.php on line 16
get_magic_quotes_gpc()という関数は定義されていませんよ、という致命的なエラー。この関数は、PHP7.4.0で非推奨になり、8.0.0で削除されました。
PHP7.4.0の時点で、この関数はfalseしか返さないようになっていたので、16行目の処理は不要となります。コメントアウトで対応。
16: //if(get_magic_quotes_gpc()) $value = stripslashes($value);
ちなみにstripslashes()という関数は、エスケープ文字を取り除いてくれるようです。get_magic_quotes_gpc()でクォートされているか確認し、trueだったらstripslashes()で取り除く、という処理だった…のかな?(想像)
これで、アクセスログが取得できるようになりました。ですが、今度は管理画面で別の新たなエラーが…。
廃止済:each()
管理画面で新たに表示されたエラーは…。
Fatal error: Uncaught Error: Call to undefined function each() in [MoguraPlusXのインストール先]/inc/function.php:629
Stack trace: #0 [MoguraPlusXのインストール先]/plugin/day_log.php(197): getuseragent('Mozilla/5.0 (Wi...')
#1 [MoguraPlusXのインストール先]/w3a.php(204): include_once('/home/...')
#2 {main} thrown in [MoguraPlusXのインストール先]/inc/function.php on line 629
each()という関数は定義されていませんよ、という致命的なエラー。この関数は、PHP7.2.0で非推奨になり、8.0.0で削除されました。
以前、この関数が非推奨になったときにいくつかの箇所で対応しましたが、対応漏れがあったようです。
この処理をしているところはいくつかありましたが、629行目の処理を例に。
629: list($browser, $browser_v) = each($v);
大雑把に説明すると、$vという配列から、現在カーソルがある行のキーと値を取り出して、カーソルをひとつ進める、という処理を行います。
取り出されたキーは$browserに、値は$browser_vに入ります。
これと同じ動きを、each()を使わずに行えばいいので、以下のように書き換えればOK。
$browser = key($v);
$browser_v = current($v);
next($v);
key()でキーを取り出し、current()で値を取り出し、next()でカーソルを進めています。
他にeach()を使用している箇所も、同じように修正します。自分の環境では、platform、browserと、あとモバイルの3箇所でした。
さいごに
以上の修正をすることで、PHP8.3.7の環境でもMogura Plus Xで正常にアクセスログが取得でき、管理ページも問題なく使用できるようになりました。
もしかしたら、まだ隠れた警告やエラーがあるかもしれないので、しばらく様子見して、見つけた問題は随時ここに追記していきます。
アクセス状況を確認するのは、今やスタンダードになっているGoogle Analyticsが便利ですが、微妙にかゆいところに手が届かないことも多いので、やはり今でもMogura Plus Xを併用しています。
この調子で、どこまでMogura Plus Xを使い続けられるかは分かりませんが、警告やエラーが出たら修正しながら、可能な限り動かして行ければと思っています。
今日の作業は以上です。お疲れ様でした!
コメント