【PHP】一見同じ文字列ながらも比較結果が期待通りにならない時の原因の調査方法

  • 2022年5月30日
  • PHP

 ダンプ関数で出力した文字列が一致している様に見えるにも関わらず文字列同士の比較が不一致となる場合があります。これは例えば次のコードです。

<?php

$a = 'ほげ';
$b = 'ほげ';

echo '$a===$b: ',($a === $b ? 'true' : 'false')."\n";
echo '     $a: '.$a."\n";
echo '     $b: '.$b."\n";
/*
$a===$b: false
     $a: ほげ
     $b: ほげ
 */

Online PHP editor | output for cTkJ7#上記コードのデモ

 PHP の文字列比較はバイト単位の比較であり、こうなっている時は大体、制御文字や文字として表現不可能なデータが混じっている時です。例えばCSVのヘッダーの1列目周りででこれが起きる時は十中八九 BOM 関連です。他にも決まったバイト数でトリミングされたことのあるデータなどもこれに陥りやすいです。

 何か違う文字が入っている、というところまではvar_dump関数を使うだけでもたどり着けます。例えば先ほどのコードならば次の様になります。

<?php

$a = 'ほげ';
$b = 'ほげ';

var_dump([
    '$a===$b' => $a === $b,
    '$a' => $a,
    '$b' => $b,
]);
/*
array(3) {
  ["$a===$b"]=>
  bool(false)
  ["$a"]=>
  string(6) "ほげ"
  ["$b"]=>
  string(7) "ほげ"
}
 */

 string(6)とstring(7)でバイト数が異なることがわかります。更に踏み込んで紛れたバイナリが何に由来するものなのか調査する場合には、見えないけど何かあるだけでなく何が入っているのかを確認する必要があります。この確認にはbin2hex関数が便利です。

PHP: bin2hex – Manual

 bin2hex関数は与えられたバイナリのデータを16進数表現にして返します。これを用いると先ほどのコードは次の様になります。

<?php

$a = 'ほげ';  
$b = 'ほげ';

var_dump([
    '$a===$b' => $a === $b,
    '$a' => bin2hex($a),
    '$b' => bin2hex($b),
]);
/*
array(3) {
  ["$a===$b"]=>
  bool(false)
  ["$a"]=>
  string(12) "e381bbe38192"
  ["$b"]=>
  string(14) "e381bb0fe38192"
}
 */

Online PHP editor | output for cfrfl#上記コードのデモ

 これで片方にだけ謎の 0x0F が紛れていることがわかりました。ここから先の調査はケース次第でまちまちです。大体バイナリと心あたりのあるものを手当たり次第にググって検証して、といったことをします。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG