[PHP]switch文の危険な2パターン

PHP

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するか指定することができます。
この場合では

  1. switch
  2. 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点を挙げさせていただきました。

PHP
スポンサーリンク
この記事が気に入ったら
いいね!しよう
最新情報をお届けします。
この記事を書いた人

スパイスファクトリー株式会社 Webエンジニア。フロントエンドやWebサイトの高速化が得意です。インフラ・バックエンドも一通りやってます。
個人的なお仕事のご依頼や情報交換などはお問い合わせまたはTwitterにメンションをお願いします。

ShoheiTaiをフォローする
このエントリーが役に立ったらシェアをお願いします!
イケてないコード – Webエンジニアのブログ

コメント

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