浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【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 が紛れていることがわかりました。ここから先の調査はケース次第でまちまちです。大体バイナリと心あたりのあるものを手当たり次第にググって検証して、といったことをします。

  • この記事いいね! (0)