PHPで何気なく使用している等号・不等号ですが、文字列と数値を比較しようとすると予期せぬ動きをすることがあります。今回はおちいりがちな落とし穴を紹介します。

まずは簡単に以下の5つについての比較を行ってみましょう。以下の6つはすべてブール値としてみるとfalseとなる値です。

  1:  null
  2:  false
  3:  0 (integer)
  4:  "" (空文字)
  5:  "0" (string)
  6:  array()

これを「==」で比較してみると以下のような結果となります。

  |1|2|3|4|5|6
--------------------
1|○|○|○|○|×|○
2|○|○|○|○|○|○
3|○|○|○|○|○|×
4|○|○|○|○|×|×
5|×|○|○|×|○|×
6|○|○|×|×|×|○

×となっている組は(1,5), (3,6), (4,5), (4,6), (5,6)の組です。これ以外にも文字列から数値のキャストなどで、おかしな挙動が多いです。興味のあるかたはDinoのhanawa氏によるPHP勉強会の発表資料を見てみるとよいでしょう。

次に数値文字列の比較について考えましょう。以下のスクリプトを見てください。

if (0 < $num && $num < 100) {
  echo "0以上100以下";
}

この場合、$num に'0xa'や'1e1'などの文字列が入っていてもこのif文を通過してしまいます。さらにやっかいなのが、この変数を整数にキャストした場合です。

if (0 < $num && $num < 100) {
  echo "0以上100以下";
  echo "\n" . intval($num);
  echo "\n" . floatval($num);
}

先ほどの'1e1'の場合、floatval()関数で比較のときの変換と同じ値に変換することができますが、intval()関数では1に変換されてしまいます。これは(int)のキャストでも同じです。'0xa'の場合はintval()、floatval()の両方で0となってしまいます。

'0xa'を10に変換するのに以下のようにします。

if (0 < $num && $num < 100) {
  echo "0以上100以下";
  $num += 0;
  echo "\n" . intval($num);
  echo "\n" . floatval($num);
}

結局のところ、数値比較を行う場合はあらかじめintval()関数を使用してから行うのが鉄則ということですね。



(アシアル 森川穣)


この記事は、アシアルが運営するPHP開発者のためのポータル&コミュニティサイト「PHPプロ!」で毎週配信しているPHP・TIPSメーリングリストを再録したものです。
同サイトでは、他にもPHP最新ニュースや、困ったときのQ&A掲示板、初心者向けのPHP講座など、PHP開発者をサポートする情報を掲載しています。