PHPのバージョンをあげたら文字化けする場合
レンタルサーバーなどでPHP5.3とかの古いPHPの提供が終了するので、PHPの切り替えをしようとしてお問い合わせをいただくことがあります。 その中で、PHPを新しいもの(*1)に切り替えたら文字化けするようになったというお問い合わせを何回かいただいたことがあります。
このケースで共通する点はだいたい以下のとおりです。
- ~PHP5.5で動作していたシステム
- 文字コードにSJISやEUC-JPを使っている(UTF-8以外)
- Laravel/CakePHPのようなフレームワークは使わずに構築されているシステム
文字化けの原因はPHP5.6で文字コードの設定が少し変わったことにあります。具体的にはdefault_charsetという文字コードを設定する項目があるのですが、
https://www.php.net/manual/ja/ini.core.php#ini.default-charset
これのデフォルト値がPHP5.5までは空だったのが、PHP5.6からは'UTF-8'に変更になったためです。default_charsetの設定はhtmlentities()のデフォルトエンコーディングの指定にも使われますが、Content-Typeヘッダーのエンコーディング指定にも使われています。
default_charsetが未設定だったシステムでは、default_charsetが空だったので、Content-Typeヘッダーは
Content-Type: text/html
のようにcharset指定がない状態で出力されていました。このため、ブラウザがHTML中のmetaタグなどに基づいてエンコーディングを判断してページを表示していました。
PHP5.6からはdefault_charsetが'UTF-8'になるため、
Content-Type: text/html; charset=UTF-8
のようにcharsetが指定されて出力されるようになり、ブラウザはSJISやEUC-JPで記述されているHTMLをUTF-8として表示しようとするので文字化けするわけです。
対策としてはdefault_charsetを適切に設定することです。Webシステムの作りにもよりますが、おそらくスクリプトの開始処理に以下のように文字コードを設定している箇所があると思います。
mb_language("ja"); mb_internal_encoding('SJIS-WIN');
これに以下のようにdefault_charsetの設定を追加します。
mb_language("ja");
mb_internal_encoding('SJIS-WIN');
ini_set('default_charset', 'SJIS-WIN');
これで、解消するはずです。文字化けでお困りの方がいましたら試してみてください。
ただし、下手に文字化けしたデータをDBに書き込んでデータを壊したりしないよう、バックアップを確実にとってから自己責任でお願いします。
現在ではWebページはほぼUTF-8で作られていますが、PHP5.3とかの時代に作られたものは、まだSJISやEUC-JPが使われていることも多かったと思います。うろ覚えですが、PHP5.6が出た2016年頃に同様の修正を大量に行った記憶があります。当時、5.5以前から5.6への移行で一番インパクトがあったのがこの変更だったのではないでしょうか。
PHP8に移行しようとすると費用的にも時間的にも大変なので、レンタルサーバーでまだ提供されているPHP5.6でとりあえず急場をしのぎたい、というお客様はいらっしゃいます。さすがに2023年現在においては、とっくにEOL(End Of Life)を過ぎているPHP5.6に移行するというのはまったく推奨できませんが、それでもPHP5.6を選択する場合は、default_charsetの設定だけで対応できるかもしれませんので試してみるのもよいかと思います。
一方、PHP5.3とかの時代に作られたシステムを一気にPHP8に対応させようとすると、修正箇所の調査や修正がそれなりに大変なはずです。
参考: PHP5からPHP8への移行は何が面倒なのか
以前書いた記事。どのあたりが大変なのかつらつらと言い訳が書いてあります。
自力で対応するのが難しい場合は、弊社でも、対応作業を承っております。詳細は「PHPの更新作業(PHP8対応作業)」をご参照ください。
(*1) PHP7/8ではまったく動作しなかったので、PHP5の最終版であるPHP5.6に切り替えてみたというケースが多いです。
投稿日:2023/02/21 15:48