はじめに
長く使っている PukiWiki を PHP 8.5 で動かせるようにしました。今回の変更は大規模な書き換えではなく、古いプラグインやライブラリで使われていた構文・関数を、現在の PHP で使える形に直す作業が中心です。
変更したファイルは 8 件です。README の対応範囲を PHP 8.3〜8.5 に更新したほか、キャスト、文字列補間、日付、正規表現、コールバックの API を見直しました。
今回変更したファイル
| ファイル | 変更 | 見直した点 |
|---|---|---|
📄 README.txt
|
PHP の対応範囲を 8.3〜8.5 に更新 | 対応バージョンを明示 |
🔢 lib/proxy.php
|
(integer) を (int) に変更 |
非推奨のキャスト名 |
🔢 plugin/search2.inc.php
|
(boolean) を (bool) に変更 |
非推奨のキャスト名 |
🔢 plugin/random.inc.php
|
(double) を (float) に変更 |
非推奨のキャスト名 |
🗓️ plugin/dump.inc.php
|
strftime() を date() に変更 |
非推奨の日付 API |
🧵 plugin/counter.inc.php
|
${...} を {$...} に変更 |
非推奨の文字列補間 |
🧵 plugin/bugtrack.inc.php
|
配列キーを含む補間を {$...} に変更 |
文字列補間の構文 |
🔎 plugin/nicovideo.inc.php
|
ereg() を preg_match() に変更 |
削除済みの正規表現 API |
なお、ファイル名が # で始まる contentsx と contents2_1 は、この環境では使っていないプラグインです。そのため、この 2 件の古い API は実際の利用機能で発生していた問題ではなく、未使用プラグインも含めてコードを PHP 8 対応にした変更として区別します。
変更が必要になった PHP のバージョン
今回の修正理由は、すべて「PHP 8.5 で削除されたから」ではありません。機能ごとに、非推奨になった時期と削除された時期が異なります。また、未使用プラグインに含まれる API と、実際に呼び出すプラグインの API は、運用上の影響を分けて考える必要があります。
| API・構文 | PHP での扱い | 今回の対応 |
|---|---|---|
(integer)、(boolean)、(double)
|
PHP 8.5 で非推奨 |
(int)、(bool)、(float) を使う |
"${var}" 形式の文字列補間 |
PHP 8.2 で非推奨 |
{$var} 形式を使う |
strftime() |
PHP 8.1 で非推奨 | 用途に合わせて date() などへ移行 |
create_function() |
PHP 7.2 で非推奨、PHP 8.0 で削除 | 匿名関数・クロージャを使う |
ereg() などの正規表現関数 |
PHP 7.0 で削除 |
preg_* 系 API を使う |
つまり、PHP 8.5 へ上げるときに初めて問題になったコードだけでなく、以前から削除されていた API に依存したコードも直しています。古いプラグインは、作成当時の PHP では動いていたというだけで、現在の PHP の API と互換とは限りません。
キャスト名は短い形式へ
PHP には (integer) と (int) のように、同じ型変換を表す複数のキャスト名があります。PHP 8.5 では (boolean)、(integer)、(double)、(binary) などの別名が非推奨になりました。変換そのものを変えるのではなく、現在推奨される綴りに揃えます。
$status = (boolean)$value;
$count = (integer)$value;
$ratio = (double)$value;
$status = (bool)$value;
$count = (int)$value;
$ratio = (float)$value;
この変更は、真偽値・整数・浮動小数点数への変換ロジックを置き換えるものではありません。PHP 8.5 が非推奨とする別名を避ける修正です。警告を放置すると、将来の PHP でより大きな互換性問題になる可能性があります。
文字列補間は曖昧さのない構文へ
ダブルクォート文字列やヒアドキュメントでは、変数を文字列に埋め込めます。PHP 8.2 では "${var}" や "${expr}" の形式が非推奨になったため、{$var} や {${expr}} の形式に直します。
配列の値を文字列へ埋め込む場合も、波括弧で範囲を明示すると読みやすくなります。
$message = "status: {$status}";
$summary = "issue: {$issue['summary']}";
これは単なる見た目の統一ではありません。文字列の中で変数や配列キーをどこまで展開するのかを、PHP のパーサーが曖昧なく判断できるようにする変更です。特に配列キーを含む式では、{$array['key']} のように対象を明示します。
strftime() と date() は書式が違う
strftime() はロケール(言語や地域の設定)に応じて日付・時刻を整形する API です。PHP 8.1 で非推奨になりました。今回の dump プラグインでは、ダウンロード用ファイル名の日付を date() で作るようにしました。
ただし、strftime() と date() は書式文字列が異なります。たとえば、年・月・日を数字で出す場合、strftime('%Y%m%d', $time) に対して date('Ymd', $time) のように書き換えます。%Y をそのまま date() に渡しても同じ意味にはなりません。
また、strftime() はロケールに応じた表記ができますが、date() は PHP の日付書式を使います。今回のようにファイル名へ数字の日付を入れる用途なら date() で足ります。一方、月名や曜日を日本語などのロケールに合わせて表示する場合は、intl 拡張の IntlDateFormatter なども含めて選び直す必要があります。置換後は、書式だけでなくタイムゾーンと出力結果も確認します。
ereg()・split() から正規表現 API へ
ereg() と split() は、古い POSIX 正規表現 API に属します。ereg() などの関数は PHP 7.0 で削除され、現在は PCRE(Perl Compatible Regular Expressions)を使う preg_* 系 API が選択肢になります。
// 文字列がパターンに一致するか調べる
$matched = preg_match('/^wiki/', $name);
// 正規表現に一致した箇所で文字列を分割する
$parts = preg_split('/[,;]/', $value);
preg_match() のパターンには /.../ のような区切り文字が必要です。また、POSIX 正規表現と PCRE は構文が完全に同じではありません。単に関数名を置き換えるだけではなく、パターン、区切り文字、大小文字の扱い、マッチ結果を確認します。preg_match() は一致時に 1、不一致時に 0、エラー時に false を返すため、エラーを区別したい場合は戻り値を厳密に扱います。
#contents2_1 のオプション解析では、= のような固定文字で分割する箇所は explode() を使えます。正規表現を使う必要がない分割まで preg_split() にするより、意図が明確でシンプルです。
おわりに
今回の 8 ファイルの変更では、キャスト名や文字列補間のように構文を更新するものと、削除済み関数を別の API に移すものがありました。特に strftime()、ereg()、split() のような API は、置換後の関数名が似ていても書式や正規表現の意味まで同じとは限りません。
PHP 8.5 対応で大切なのは、エラーや非推奨警告を機械的に消すことだけではなく、「そのコードが何をしたいのか」と「置き換え先の API が何を保証するのか」を確認することです。プラグインの利用箇所ごとに、出力・検索・分割・リンク生成などの動作を確かめながら更新していきます。