PHPのswitch文はなかなか曲者という話はちょくちょく聞いてましたが、
今回、少しばかりswitch文でハマりました。
失敗談のついでにswitch文で気をつけなければならないことをまとめていきます。
switch文におけるcontinueの扱い
まず、僕を貶めたコードを御覧ください。
$list = array('a','b','c'); //$listの中身をチェックしていく foreach($list as $value) { switch($value) { case 'a': echo 'こんにちは'; break; case 'b': echo 'こんばんは'; continue; } echo '(*´ェ`*)テレリコ'; }
はい、僕のイメージでは$valueに’b’が来たとき、
foreachをcontinueして欲しいと思っていました。
しかし実際はcontinueされずに「(*´ェ`*)テレリコ」が表示されます。
switch文ではcontinueとbreakは同等!?
実はPHPのswitch文でcontinueを使うとbreakと同じ働きをします。
なので極端な話
switch($value) { case 'a': echo 'こんにちは'; continue; //break; case 'b': echo 'こんばんは'; continue; //break; }
こうした場合でもbreakと全く同じ動きをするのです。
じゃあどうすればいいの!!
って思った方。こんな書き方ができます。
//$listの中身をチェックしていく foreach($list as $value) { switch($value) { case 'a': echo 'こんにちは'; break; case 'b': echo 'こんばんは'; continue 2; } echo '(*´ェ`*)テレリコ'; }
continueやbreakの後に数字を書くことで、書いた位置からいくつ分の
ループをbreak/continueするか指定することができます。
この場合では
- switch
- foreach(continueする)
という順でループ(switchもループと見る)を抜けていきます。
これはswitch文の中だけでなく、ループの制御であればなんでも使えます。
switch文におけるcaseとの比較
PHPのswitch文では緩やかな比較、つまり==演算子を使用しています。
これを頭に入れておかないと重大なバグの原因になるので気をつけましょう。
例えばこんな時。
$value = ''; switch ($value) { case 0: echo '0'; break; case 1: echo '1'; break; default: echo 'default'; }
普通ならdefalutが出力されると思いますが…この場合は0を出力します。
==演算子で比較しているため裏でキャストが働いてtrueに返っちゃうわけですね。
switchじゃ厳密な比較はできないの!?
そんなことはありません。やろうと思えばできるんです。
switch文で型を考慮した比較を行う方法
その方法がこちら。
$value = ''; switch (true) { case $value === 0: echo '0'; break; case $value === 1: echo '1'; break; default: echo 'default'; }
switch文の頭はtrueで素通りさせて、caseに===演算子による比較を入れることで
型も考慮した厳密な比較をすることができます。
ただ、ここまでくるとif文で書けば?っていう人もいるかもしれないですね。。
正直ここは好みの問題になってくるとは思います。
以上、switch文を使用する上で気を付けなければならないこと、
2点を挙げさせていただきました。
コメント