PHP
switch

[関数系] PHPのswitch文の落とし穴「===」厳密比較じゃない・・・


概要

switch文をif文に書き換えるということをこの前やったが、そういえばという程度のメモ。ただ、余裕がないときにハマると厄介な気がするので、残しておく。


始まり

以下のようなswitch文があり、一つの分岐が必要なくなる事態が発生した。

以下の文でいうと、case 1の場合が必要なくなったと考えてもらえば良い。

ちなみにdefault文はなかった。


元のswitch文


switch ($sample) {
case 0:
echo 'iは0に等しい';
break;
case 1:
echo 'iは1に等しい';
break;
}

ただ、case1がないとするとif文に書き換えた方が読みやすそうだ。じゃあそうしよう。default文もないし。まあ、リスク避けたいし、普通に厳密比較で書けば良いよね。

if ($sample === 0) {

echo 'iは0に等しい';
}

そして実行・・・あれ?echoされなくない・・・確かめると・・・


今回の問題


$sampleは実はstringで入って来てた

つまり、if文でいうと以下のような比較が行われていたわけで・・・

if ($sample == 0) {

echo 'iは0に等しい';
} else if ($sample == 1) {
echo 'iは1に等しい';
}

これだと文字列の0でもintの0でもなんなら・・・と言った感じに曖昧な比較となる。(知っている人がほとんどだろうからあとは何もいうまい。)

いやちょっと待ってくれ。そこはintで渡しておけ・・・とか、おま・・・・。という小言は置いておいて。その時は0の方が正しい値(もちろん現実ではマジックナンバーが使用されていたわけではないが)だったため、$sampleの方を強制的にintに変換することで(納得いかないけど)対応した。

でもswitch文の方が読みやすい場合もあるので、switch文での厳密比較もしたいよね。


switch文で厳密比較する場合にはどうするのか


元のswitch文


switch ($sample) {
case $sample === 0:
echo 'iは0のintegerに等しい';
break;
case $sample === '0':
echo 'iは0のstringに等しい';
break;
}

という感じになる。現場からは以上です。


参考

PHPのswitchで厳密な型比較