PHP
新人プログラマ応援

はじめに

  • 条件分岐の構文でswitch構文がありますが、これは思わぬ罠があったりするので極力使いたくない
  • その割にどの参考書にも出てくるし新人プログラマは割と使いがち→結果罠を踏んでデバッグすることに…
  • そうならないようによくある罠を知っておくのと、switch文を使わないでやりたいことを実現できるテクニックを紹介します
  • 今回はPHPswitch文について取り上げます

罠1

PHPswitch文は曖昧比較されます。例えば以下の出力は何になるでしょうか?

sample1.php
<?php
$sample = 1;
switch($sample){
case true:
    echo 'これはtrueです'."\n";
    break;
case 1:
    echo 'これは数値の1です'."\n";
    break;
default:
    echo 'これは1ではありません'."\n";
    break;
}

出力は以下になります

これはtrueです

内部的には$sample == trueになってるからですね。
曖昧比較はバグの温床になりやすいのでオススメできません。

罠2

フォールスルーと呼ばれるものです。以下のコードの出力は何になるでしょうか?

sample2.php
<?php
$sample = 'a';
switch($sample){
case 'a':
    echo 'これはaです'."\n";
case 'b':
    echo 'これはbです'."\n";
case 'c':
    echo 'これはcです'."\n";
default:
    echo 'これはa,b,cではありません'."\n";
}

出力

これはaです
これはbです
これはcです
これはa,b,cではありません

うっかりbreakを書き忘れるとその下のcase文まで実行されてしまいます。
これを使ったテクニックなどもありますが、意図せず複数のcaseが実行される可能性がありこれもバグの温床になりやすくオススメできません。

回避テクニック

上記のような罠があるのでswitch文を使うのをやめましょう。
代わりに以下のような形にすると回避できることがあります(100%全ケースに対応できるわけではないので注意)

sample1_improvement.php
<?php
$sample_array = array(
    true => 'これはtrueです',
    1    => 'これは1です',
);

$sample1 = 1;
if(isset($sample_array[$sample1])){
    echo $sample_array[$sample1]."\n";
} else {
    echo 'これは1ではありません'."\n";
}

出力

これは1です
sample2_improvement.php
<?php
$sample_array = array(
    'a' => 'これはaです',
    'b' => 'これはbです',
    'c' => 'これはcです',
);

$sample1 = 'a';
if(isset($sample_array[$sample1])){
    echo $sample_array[$sample1]."\n";
} else {
    echo 'これはa,b,cではありません'."\n";
}

$sample2 = 'd';
if(isset($sample_array[$sample2])){
    echo $sample_array[$sample2]."\n";
} else {
    echo 'これはa,b,cではありません'."\n";
}

出力

これはaです
これはa,b,cではありません

あらかじめ配列を用意しておき、それのキーアクセスを利用することで分岐を減らしています。
これの良いところは正解として通す一覧を配列で持つことで分かりやすいのと、case文の分コードが長くならないところです。
例えばd,e,f,gまであと4つ増やしたとしてこの例では配列に4つ足すだけで実現可能です。
配列もホワイトリストとして利用できるのでcase文より使いまわしやすい形になっているかと思います。
反面、配列内にあるかどうかissetで調べる必要はあります。

おわりに

タイトルで撲滅って言ってますが、別に撲滅しなくてもいいです。
罠を把握した上で適切な使い方をしていきましょう :muscle: