C#er な私が PHP の記事なんて書くことになるとは...。ペチパーな方には当たり前かもしれませんが、最近業務でハマったのでメモとして残します。
こんな時間まで仕事するなんて完全に負け組感ある。チキショー、PHPなんて嫌いだ。
— じんぐる (@xin9le) 2015, 2月 3
症状
以下のような単純な PHP があるとします。.php ファイルの形式は UTF-8。これの Content-Length は 11 です。呼び出し元も 11 バイトの結果が返ることを期待しています。
<?php echo "Fuckin' PHP"; ?>
だけどなぜか 14 バイト返ってくる。「この 3 バイトは何なんだ!」と調べてみると BOM (Byte Order Mark) でした。BOM を付けるか付けないかの制御をするコードなんてどこにもないのにどうして...!
原因
結論から言うと、実行コードが書いてある .php ファイルが BOM 付きの UTF-8 で保存されている場合、echo した結果に BOM が乗ります。どうしてこんな動きをするのかはサッパリですが、実際そうなります。なので BOM が付かない形式の UTF-8 で .php ファイルを保存すれば解決します。
さらに気を付けなければならないのは、echo をしてレスポンス本体に書き込んでいる .php ファイルだけではなく、require_once で読み込んでいるファイルに BOM が乗ってもダメということです。今回はこれに気付いておらず、何時間もムダにしました。
PHP の編集にメモ帳は使うな!
どうしてこうなったか。経緯は以下のような感じです。
- とある環境で動いていた PHP 製の API をサーバー移転のためにお引っ越し
- 一部の文字列リテラルに修正があったので、サーバー配置後にメモ帳で編集
- テストしたら呼び出し側でエラー発生
- why...!? (← BOM が入っていることが考慮されていないので戻り値の解析に失敗
その後に BOM が乗っていることに気付いたのですが、どこで混入したかというとメモ帳 (notepad.exe) で編集したときです。どうやらメモ帳は UTF-8 形式で保存する際に必ず BOM を付加する仕様のようです。.php の編集をするときは Notepad++ や秀丸エディタ、サクラエディタなど、BOM なしで保存できるツールを使うようにしましょう。
神聖なる notepad.exe 様だけで開発できない非コンパイル言語に何の価値があろうか(いやない)
#FuckinPHP
— じんぐる (@xin9le) 2015, 2月 5
おまけ
@PharaohKJ さんから終了タグも書かない方が良いと教わりました。(なんかこう、邪悪な方向に) 奥が深いな PHP...。
@xin9le 最後の ?> も無い方がいいよ。 http://t.co/lAnG1naryY
— ふぁらお加藤 (@PharaohKJ) 2015, 2月 5