PHPの文字コードUTF-8 BOM付ではまった話

APIを作っているときにはまった話です
結論を先にいうと『PHPファイルがUTF8のBOM付で保存されていた』です

WEBサーバー上にアップロードするファイル(HTML、PHP、CSS、JavaScript等)はUTF8で保存しています。
いつもはSublime Textをメインで使ったりサクラエディタを使ったりしていて保存するときに文字コードだけ気をつけているのですが、今回住所情報用のAPIでJSONを作成したときにはまりました

修正が多かったのでローカル環境で編集せずにサーバーにFTP接続して直接編集をしていました
Notepad++を使って・・・

JSON形式のデータを作るまではよかったものの、PHPでJSONを吐き出す際に可読性をあげようと日本語(2バイト文字)をユニコードエスケープさせないようにと考えて

と『JSON_UNESCAPED_UNICODE』オプションをつけて吐き出しました

オプションをつけずに『json_encode()』で出力すると2バイト文字はユニコードエスケープされて化されてしまうので可読性が落ちてしまいます

これは可読性の問題だけであって、そんな状態のJSONデータを読み込んで処理してもちゃんと2バイト文字として戻りますのでそのままでも問題ありません
ただ、みなさんに使ってもらいたいものでもあるので可読性をよくしたいというのもありますし、自分自身が【キレイにしたい】という気持ちです

話は戻ってBOM付にはまった問題ですが、作成したJSON形式データを読み込むテストをしているときに「ん?BOM付で出力されてる」というのは気がついていましたが、BOM付のJSONデータでも『json_decode()』する際に工夫すればBOMを落とせるのでスルーしていました
※BOMを落とさずに『json_decode()』するとNullが返ってきます

ステータスコードや件数を取得して「うまくいったな」と思っていたのですが2バイト文字が取得できていない・・・
『var_dump』を使ってデコードしたJSONの中身を見ると文字列はちゃんと見えてるのに・・・

半角英数字(1バイト)は取得できるのに2バイト文字が取得できないということはエンコードの問題かなと考えて『mb_convert_encoding()』をやり方を変えてみたりとしましたがうまくいかない
サーバーのエラーログにもログははかれていない

JSONデータは思うように表示できていたので処理する側の問題だと思って試行錯誤してみましたがどうにもならない・・・
無駄な時間だけが過ぎていくので基本に戻ろうと思い直し、『json_encode()』を使う際の『JSON_UNESCAPED_UNICODE』オプションを外してみると2バイト文字がちゃんと取得できた!

できた!解決!といきたいところでしたが、できたはいいけど可読性が落ちてしまうのはちょっと・・・
そもそも本当に解決したとは言えません
そこで、もっと基本に戻るべきだと考えて、簡単な配列をJSONにする新しいファイルをローカル環境で1から作成してアップロードして試してみると2バイト文字でもちゃんと取得できました

ということはファイル自体の問題かというのが見えてきました
(まさかBOM付で保存されているとはまだ気がついてません)

ブラウザベースでPHPスクリプトを叩いてたのをサーバーから直接叩いてみます

でた。
JSONで吐き出すのでPHPスクリプトの最初に『header( “Content-Type: application/json; charset=utf-8” );』を記述していますが、『headerを出力する前に他のものを出力するんじゃないよ』と注意されています

・ローカルでファイルを作らずにNotepad++でファイルを作ってた
・余計な記述をしていないの注意されている
・読み込み処理のときにBOMを落とさなければいけなかった
大体なんでBOMが付いてんだ!?

ここでやっとPHPファイル自体におかしなことが起きていることが確定しました
もっと前にサーバーで直接叩けばよかった・・・

サーバーからファイルを落としてきてサクラエディタで開いて保存形式を確認
UTF8のBOM付
BOMが付いてました

BOM無しに保存し直してサーバーにアップロードし、確認してみると『JSON_UNESCAPED_UNICODE』を付けても2バイト文字がちゃんと取得できるようになりました
『json_decode()』の時にBOMを落としても、JSONを出力しているファイルそのものがおかしければ見た目が正常でもうまく動かない現象が起こります

ファイルは必ずBOM無しで保存してアップロードしましょう

Notopad++が初期設定がBOM付きになっているので気をつけましょう
Notopad++の設定を変える方法はこちらです