xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

PHPのechoにBOMが混入するのを防ぐ

C#er な私が PHP の記事なんて書くことになるとは...。ペチパーな方には当たり前かもしれませんが、最近業務でハマったのでメモとして残します。

症状

以下のような単純な 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 ファイルを保存すれば解決します。

PHP file editing using notepad.exe

さらに気を付けなければならないのは、echo をしてレスポンス本体に書き込んでいる .php ファイルだけではなく、require_once で読み込んでいるファイルに BOM が乗ってもダメということです。今回はこれに気付いておらず、何時間もムダにしました。

PHP の編集にメモ帳は使うな!

どうしてこうなったか。経緯は以下のような感じです。

  1. とある環境で動いていた PHP 製の API をサーバー移転のためにお引っ越し
  2. 一部の文字列リテラルに修正があったので、サーバー配置後にメモ帳で編集
  3. テストしたら呼び出し側でエラー発生
  4. why...!? (← BOM が入っていることが考慮されていないので戻り値の解析に失敗

その後に BOM が乗っていることに気付いたのですが、どこで混入したかというとメモ帳 (notepad.exe) で編集したときです。どうやらメモ帳は UTF-8 形式で保存する際に必ず BOM を付加する仕様のようです。.php の編集をするときは Notepad++秀丸エディタサクラエディタなど、BOM なしで保存できるツールを使うようにしましょう。

おまけ

@PharaohKJ さんから終了タグも書かない方が良いと教わりました。(なんかこう、邪悪な方向に) 奥が深いな PHP...。