【PHP Tips】比較演算子 == と === の違い【暗黙的キャストの罠】

PHP
スポンサーリンク

概要

PHPで2つの値が等しいかを比較する際の比較演算子は「==」と「===」の2種類存在します。
前者は型変換(暗黙的キャスト)をして値の比較を行いますが、後者は型も含めて値が一致しているかを比較します。

この型変換(暗黙的キャスト)を意識していないと条件分岐がうまくできなかったりするので注意が必要です。

【悪い例】== を使用して文字列と数値を比較する

プログラム

<?php

$var = 0;
if($var == 'test'){
	echo 'aaa';
}
echo 'bbb';

?>

期待する実行結果

bbb

実際の実行結果

aaabbb

なぜうまく比較ができないのか

本来は「0 」と「test」は値が一致しないので、ifの条件式はFALSEとなるはずです。
しかし、今回の場合はTRUEと判定されて、中のechoが実行されてしまっています。

これは、「==」で値の比較を行った際に「0」という数値に対して「test」という文字列を比較する前に、「test」の型変換が行われることが原因です。
「test」という文字列に対応する数値がないので「0」に置き換えられてしまい、ifの条件式がTRUEとなります。

この型変換(暗黙的キャスト)のルールはPHPのマニュアルにも記述があります。

整数値を文字列と比較したり、比較に数値形式の文字が含まれる場合は、文字列が 数値に変換され、 数値としての比較を行います

https://www.php.net/manual/ja/language.types.string.php#language.types.string.conversion

数値として文字列が評価された時、結果の値と型は次のように定義されます。
文字列の中に ‘.’ や ‘e’、’E’ といった文字が含まれず、 数値が integer 型の範囲内 (PHP_INT_MAX で定義されています) におさまる場合は integer として評価されます。それ以外の場合は、すべて float として評価されます。
文字列の最初の部分により値が決まります。文字列が、 有効な数値データから始まる場合、この値が使用されます。その他の場合、 値は 0 (ゼロ) となります。有効な数値データは符号(オプション)の後に、 1 つ以上の数字 (オプションとして小数点を 1 つ含む)、 オプションとして指数部が続きます。指数部は ‘e’ または ‘E’ の後に 1 つ以上の数字が続く形式です。

https://www.php.net/manual/ja/language.types.string.php#language.types.string.conversion

解決策

解決策には以下の方法が考えられます。
そもそも、数値と文字列を比較するなよって話になるのですが…

  • ifの条件式での右辺を「1」などの数値にする。
  • 「==」ではなく「===」を使う
    ※この場合に、ifの条件式の右辺を ‘0’ とすると当然TRUEになりません。
  • $var = ‘0’ のように文字列として「0」を変数に入れる。

さいごに

こうやってまとめてみると、こんなことやる奴いないだろ!ってなるのですが、実際に現場で見たことがあります…
PHPは動的型付け言語で簡単に思われますが、逆にこのような仕様としての型変換(暗黙的キャスト)を意識しないでいると思わぬバグにつながる可能性があるので注意したいですね。

コメント

タイトルとURLをコピーしました