PHPでShift-JISに変換エンコードしたCSVをダウンロードする機能を実装したのですが、日本語の文字化けが発生。
この問題がちょっとややこしくて解決するのに時間がかかりました。
なんと文字化けの原因はソースコードではなくて、PHPファイルの文字コードだったんです。
これはなかなか気づきませんね。
同じような事象でハマっている方の参考になればと思い解決方法を解説します!
スポンサーリンク
目次
【発生事象】Shift-JISに変換しているCSVのダウンロード処理でのみ文字化けする
まずは、どのような状況で発生したのか整理します。
解決方法のみ知りたいという方は読み飛ばしてしまってください。
文字化けするのはダウンロードするCSVのみです。
通常のWebページは文字化けせず正常に表示されています。
文字コードは、通常のページは全てUTF-8で、CSVダウンロードの時のみ、mb_convert_encodingでShift-JISにエンコードしています。
エンコードのソースコード(このあとの調査の結果このソースコードには問題は無いことがわかりました)
mb_convert_encoding($str, 'sjis', 'utf-8');
このPHPシステムと全く同じものを、他のPCやサーバーでも動かしていますが、この事象が発生するのは、新規にセットアップした1台のPCでのみ発生しています。
ソースコードも同じですし、php.iniの文字コード関連も見直しましたが改善せずです。
【調査】実はShift-JISのエンコードはちゃんと出来ていたがBOMが付いている!
実際に行った調査 の内容について。
ここも解決方法のみ知りたいって方は読み飛ばしちゃってください〜
Shift-JISへのエンコードは出来ているっぽい
文字コードを指定できるツールで文字化けしているCSVをShift-JISで開いてみる事に。
IE(Internet Explorer)で簡単に文字コードを指定して開けます。
csvの拡張子を、txtに変更してIEにドラッグ&ドロップしてみます。
(csv拡張子のままだと、素直に開いてくれませんでした。)
開けたら画面を右クリック、「エンコード」→「日本語(シフトJIS)」とクリックすればOK。
なんとこの方法でShift-JISで開いたら、文字化けせずに表示さたんです!
ということは、Shift-JISのエンコードは問題ない?
でもなぜEXCELなどで開くと文字化けするのか…?
謎が深まるばかり…
BOMが付いている!
そこで、SublimeTextでファイルを開いてみました。
UTF-8 with BOM!?
確かにShift-JIFにエンコードしているはずで、エンコードもうまくいっているはず。
なのになぜかUTF-8 with BOMとして認識されている!
【原因】BOMヘッダが付加されてUTF-8と認識される
原因はこのBOMなんですね。
どうやら大概のツールは文字コードを判定する際にBOMヘッダが付加されていると実際の文字コードに関係なくUTF-8で開くようです。
Shift-JISにエンコードしているのに、UTF-8で開いていたら文字化けして当然ですね。
このCSVは、Shift-JISなのにBOMが付いているから、ツールがUTF-8と勘違いして文字化けして表示しているって事です。
これはなかなか気づきませんね。
普段BOMなんて気にしてませんし、なんでBOM付いているのか謎ですしね。
【解決方法】PHPファイルをBOM無しのUTF8に変換する事で解決
ではなんでBOM付きのShift-JISのファイルが出来上がってしまったのでしょうか?
PHPは、ソースファイルがBOM付きだとechoした結果にもBOMが付くのです。
require_onceしたファイルのどれかにBOMがあっても同様です。
ようするに。
Shift-JISにエンコードしているが、PHPファイルがBOM付だと、BOM付きのShift-JISのCSVを出力するんです。
ツールは「BOMが付いてるからUTF-8だね!」って判断して、文字化け発生するという流れです。
PHPの開発ってだいたいBOM無しのUTF-8でしてますよね。
なので、基本的にこの事象はおきないのですが…
今回は新しい環境にモジュールをセットアップしたのですが、その時に環境依存のconfig系のPHPをさくっとメモ帳で修正してました。
メモ帳はUTF-8をBOMありでしか保存出来ないのです。
なので、メモ帳で修正を保存した時に、BOMが勝手に追加されていたんですよ。
という事で、そのPHPファイルをBOM無しのUTF-8に変換する事で、文字化けは解決しました!
まとめ:PHPファイルをメモ帳で修正しない!
予想外の所に原因がありましたね!
そもそもPHPファイルはメモ帳で修正したらダメなんですね!
どこかでこんな教訓を見たような気もしますか、すっかり忘れてました。
実際に体験すると身につくものですね!
最後までお読みいただきありがとうございました!