はじめに
今回は、APIレスポンスで受け取った値である"SUCCESS"が代入された$response_dataを
$string = "SUCCESS"
$response_data = curl_exec($ch); //文字列SUCCESSが代入される前提とし、curlを使うまでの処理は省いて書いています
if(trim($response_data) == trim($string)){
上記if文で、等価比較した時にfalseになってしまった事象についての備忘録として残しておきたいと思います。
結論 BOMのせい
結論から言うと、レスポンスで返される"SUCCESS"がBOM付きで返されていたことが原因でした。
$ curl -s -X POST -d "name=test&email=test@example.com" https://example.com/submit
SUCCESS
$
上記はコンソールでのAPIリクエストの例ですが、見た目上は"SUCCESS"が返されていています。
しかしxxdコマンドを使い、ファイルの先頭の数倍とを16進数で表示させてみます。
BOM付きUTF-8であれば、ef bb bf が表示されます
$ curl -s -X POST -d "name=test&email=test@example.com" https://example.com/submit | xxd
efbb bf53 5543 4345 5353 ...SUCCESS
SUCCESS
$
efbb bfが表示されていて、BOM付きであることが分かりました。
そのBOMってなに?
BOM は Byte Order Mark の略で、Unicodeテキストの先頭に付加される数バイトの特殊な文字です。 主な目的は、テキストがどのUnicodeエンコーディング(UTF-8、UTF-16、UTF-32)で書かれているかを識別することです。 BOM自体は不可視文字なので、通常は表示されません。
UTF-16とUTF-32では、BOMは通常必要で、UTF-8の場合BOMがなくてもエンコーディングを判別できる場合が多く、BOMは必須ではありません。
今回はUTF-8ですが、APIの実装でBOMを付加していたようです。
なぜBOMがついているとfalseになる?
falseになってしまう理由は、等価演算は2つのバイト列の比較を行っているからでした。
BOMがついていることにより、同じ見た目の文字列でもバイト列が違っているからfalseになってしまったのです。
xxdを用いたときに表示されたef bb bf 53 55 43 43 45 53 53がBOM付きのUTF-8バイト列で
53 55 43 43 45 53 53こちらがBOMなしのUTF-8バイト列になります。
まとめ
- 等価比較は2つのバイト列を比較する
- 同じに見える文字列でも、BOMが付いていてバイト列が違うかもしれない
- curlで返ってきた文字列のバイト列を知りたい時は、
| xxdをつかう