MENU

【PHP】switch文とmatch式の使い方を解説|Webの基礎

PHPのswitch文とmatch式の使い方を解説|Webの基礎
目次

はじめに

前回の記事では、if文による条件分岐について解説しました。

今回は、条件分岐のもう1つの書き方であるswitch文と、PHP 8から使えるようになったmatch式について解説します。どちらも「1つの値に応じて処理や結果を切り替える」ときに便利な構文です。

switch文とは?

switch文は、1つの値を複数の候補と順番に比べて、一致したところの処理を実行する構文です。

たとえば、会員ランクによって表示を変える処理をif文で書くと、次のようになります。

<?php
    $rank = "gold";

    if ($rank == "gold") {
        echo "ゴールド会員:10%割引";
    } elseif ($rank == "silver") {
        echo "シルバー会員:5%割引";
    } else {
        echo "一般会員:割引なし";
    }

$rank ==の比較が何度も出てきます。このように「同じ変数を、いくつかの値と比べる」処理は、switch文を使うとすっきり書けます。

VBAのSelect Caseと同じ役割の構文です。ただし、VBAのSelect Caseは一致したCaseを実行すると自動で抜けますが、PHPのswitch文はbreakを書かないと抜けません(詳しくは後述します)。

switch文の基本(case・break・default)

switch文は、次の形で書きます。

switch (比べる値) {
    case 候補1:
        // 候補1と一致したときの処理
        break;
    case 候補2:
        // 候補2と一致したときの処理
        break;
    default:
        // どれにも一致しなかったときの処理
}

先ほどの会員ランクの例をswitch文で書き直すと、次のようになります。

<?php
    $rank = "gold";

    switch ($rank) {
        case "gold":
            echo "ゴールド会員:10%割引";
            break;
        case "silver":
            echo "シルバー会員:5%割引";
            break;
        default:
            echo "一般会員:割引なし";
    }

実行すると「ゴールド会員:10%割引」と表示されます。それぞれのキーワードの役割は次のとおりです。

キーワード役割
case 値:比べる値と一致したら、ここから処理を始める
break;switch文を抜ける
default:どのcaseにも一致しなかったときに実行する(省略可)

breakを忘れると次のcaseまで実行される

switch文でいちばん注意したいのがbreakです。breakを書かないと、一致したcaseの処理を実行した後、その下のcaseの処理まで続けて実行されます。これをフォールスルーと呼びます。

<?php
    $rank = "gold";

    switch ($rank) {
        case "gold":
            echo "ゴールド会員:10%割引";
        case "silver":
            echo "シルバー会員:5%割引";
        default:
            echo "一般会員:割引なし";
    }

このコードを実行すると、3つのメッセージがすべて表示されてしまいます。$rankは"gold"なのでcase "gold":から処理が始まりますが、breakがないため、そのまま下のcase "silver":やdefault:の処理まで実行されるからです。

switch文でbreakがある場合はcase "gold"の処理だけで抜け、breakがない場合は下のcaseやdefaultの処理まで続けて実行される様子を比べた図

breakを書き忘れてもエラーにはならないため、気づきにくいミスです。「一致しないはずのメッセージまで表示される」ときは、まずbreakの書き忘れを疑ってください。

複数のcaseで同じ処理をまとめる

フォールスルーの仕組みを利用すると、複数の値で同じ処理を実行したい場合にcaseをまとめて書けます。

<?php
    $day = "土";

    switch ($day) {
        case "土":
        case "日":
            echo "定休日です";
            break;
        default:
            echo "営業しています";
    }

$dayが"土"のときは、case "土":に処理がないため、そのままcase "日":の処理へ進み「定休日です」と表示されます。"日"のときも同じ結果になります。

switch文は「==」で比較する

switch文での値の比較は、演算子の記事で解説した==と同じ、型を自動変換する比較で行われます。そのため、型が違っても値が一致すれば、そのcaseが実行されます。

<?php
    $input = "10"; // フォームから届いた文字列を想定

    switch ($input) {
        case 10:
            echo "10と一致しました"; // 文字列"10"でも一致する
            break;
        default:
            echo "一致しません";
    }

多くの場合は便利に働きますが、nullとfalseが一致してしまうなど、意図しない一致が起こることもあります。型まで含めて厳密に比べたい場合は、次に紹介するmatch式を使います。

match式(PHP 8から使える)

match式は、PHP 8で追加された構文です。switch文と同じように1つの値を複数の候補と比べますが、一致した候補に対応する「値」を返すのが特徴です。

<?php
    $rank = "silver";

    $discount = match ($rank) {
        "gold"   => "10%割引",
        "silver" => "5%割引",
        default  => "割引なし",
    };

    echo $discount; // 5%割引

候補 => 返す値の組み合わせをカンマで区切って並べます。一致した候補の値が$discountに代入されます。最後は};のように、セミコロンで閉じる点に注意してください。

match式には、switch文と比べて次のような特徴があります。

breakが不要

match式では、一致した候補の値を返した時点で終了します。switch文のようにbreakを書く必要はなく、書き忘れによるフォールスルーも起こりません。

===で比較する

match式は===で比較するため、型が違えば一致しません。

<?php
    $input = "10";

    echo match ($input) {
        10      => "数値の10と一致",
        "10"    => "文字列の\"10\"と一致",
        default => "一致しません",
    }; // 文字列の"10"と一致

switch文ではcase 10:に一致した値が、match式では"10"(文字列)の候補に一致しています。

カンマで複数の候補をまとめられる

複数の値で同じ結果を返したいときは、候補をカンマで区切って並べます。

<?php
    $day = "日";

    echo match ($day) {
        "土", "日" => "定休日です",
        default    => "営業しています",
    }; // 定休日です

どれにも一致しないとエラーになる

match式で、どの候補にも一致せずdefaultもない場合は、UnhandledMatchErrorというエラーになり処理が止まります。

<?php
    $rank = "bronze";

    echo match ($rank) {
        "gold"   => "10%割引",
        "silver" => "5%割引",
    };
    // Fatal error: Uncaught UnhandledMatchError: Unhandled match case 'bronze'

switch文では、一致するcaseがなければ何も実行されずに終わるだけですが、match式は想定外の値をエラーとして知らせてくれます。想定外の値が来る可能性がある場合は、defaultを書いておきましょう。

match (true)と書き、候補の部分に$score >= 90 => "A"のような条件式を並べると、範囲による判定もできます。ただし、範囲で分ける処理は前回の記事で解説したif文のほうが読みやすい場合も多いので、慣れるまではif文を使うのがおすすめです。

switch文とmatch式の使い分け

switch文とmatch式の違いを整理すると、次のようになります。

switch文とmatch式の違いを、比較方法・breakの要否・値を返すか・複数の値のまとめ方・一致しない場合の動作の5項目で比べた図
項目switch文match式
比較の方法==(型を変換して比較)===(型まで比較)
break必要(忘れるとフォールスルー)不要
値を返すか返さない(処理を実行する)返す(変数に代入できる)
複数の値をまとめるcaseを縦に並べるカンマで区切る
一致しない場合何もしないエラー(UnhandledMatchError)
使えるバージョンすべてPHP 8以降

使い分けの目安は次のとおりです。

  • 値に応じて「1つの値」を決めたい → match式(表示ラベル・割引率・色など)
  • 値に応じて「複数行の処理」を実行したい → switch文(メッセージを複数表示する、別の処理を呼び出すなど)

match式はPHP 8以降でしか使えません。PHP 7系のサーバーで動かすとParse errorになります。レンタルサーバーなどで古いPHPが使われている場合は、サーバーの管理画面でPHPのバージョンを確認してください。

実務サンプル(注文ステータスを表示用に変換する)

ネットショップの注文管理画面を想定し、データとして保存されている注文ステータス("pending"・"shipped"などの英字)を、画面に表示する日本語のラベルと色に変換するサンプルです。表示用の値はmatch式で決め、ステータスごとに複数行の案内を出す部分はswitch文で書き分けています。

注文ステータスpending・paid・shipped・cancelledと、それ以外の値が、それぞれどの表示ラベルと色に変換されるかを示した対応図
<?php
    // データベースなどから取得した注文ステータスを想定
    $status = "pending";

    // ① match式で、表示ラベルを決める
    $label = match ($status) {
        "pending"   => "入金待ち",
        "paid"      => "入金済み",
        "shipped"   => "発送済み",
        "cancelled" => "キャンセル",
        default     => "確認中",
    };

    // ② match式で、表示する色を決める(入金済みと発送済みは同じ色)
    $color = match ($status) {
        "pending"         => "#e37400",
        "paid", "shipped" => "#1e8e3e",
        "cancelled"       => "#d93025",
        default           => "#5f6368",
    };

    echo "<p>注文状況:<span style=\"color: {$color};\">{$label}</span></p>";

    // ③ switch文で、ステータスごとに複数行の案内を出し分ける
    switch ($status) {
        case "pending":
            echo "<p>3日以内にお支払いください。</p>";
            echo "<p>期限を過ぎると自動でキャンセルされます。</p>";
            break;
        case "paid":
            echo "<p>発送の準備を進めています。</p>";
            break;
        case "shipped":
            echo "<p>2〜3日後にお届け予定です。</p>";
            echo "<p>配送状況は追跡番号から確認できます。</p>";
            break;
        case "cancelled":
            echo "<p>返金手続きを進めています。</p>";
            break;
        default:
            echo "<p>ご不明点はお問い合わせください。</p>";
    }

$statusが"pending"の場合、ブラウザには次のように表示されます(「入金待ち」はオレンジ色で表示されます)。

注文状況:入金待ち
3日以内にお支払いください。
期限を過ぎると自動でキャンセルされます。

$statusを"shipped"に変えると「発送済み」が緑色で表示され、お届け予定の案内に切り替わります。想定していない値(たとえば"returned")が入った場合も、defaultによって「確認中」と表示されるため、エラーで画面が止まることはありません。

よくある質問・エラー対処

Q. switch文で、一致しないはずのcaseの処理まで実行されます

→ breakの書き忘れが原因です。一致したcaseの処理の最後にbreak;があるか確認してください。


Q. Uncaught UnhandledMatchErrorというエラーが出ます

→ match式で、どの候補にも一致しない値が渡されたときのエラーです。エラーメッセージのUnhandled match caseの後ろに、一致しなかった値が表示されます。候補を追加するか、defaultを書いてください。


Q. match式でParse error(syntax error)が出ます

→ 次の点を確認してください。

  • PHPのバージョンが8以降か(PHP 7系ではmatch式を使えません)
  • 最後の}の後ろにセミコロン(;)があるか
  • 候補と値の区切りが=>になっているか(:ではありません)

Q. if文・switch文・match式はどう使い分ければいいですか?

→ 範囲(「80点以上」など)や複数の変数を組み合わせた条件ならif文、1つの値がどれと一致するかで分けるならswitch文かmatch式、が目安です。さらに、結果として1つの値を決めたいだけならmatch式を選ぶと、短く安全に書けます。

おわりに(まとめ)

まとめ

1つの値に応じて処理や結果を切り替えるなら、switch文とmatch式が便利です。

  • ✅ switch文はcaseで候補を並べ、一致したcaseの処理を実行する
  • ✅ breakを忘れると、下のcaseの処理まで続けて実行される
  • ✅ switch文は==(型を変換して比較)で比べる
  • ✅ match式(PHP 8〜)は===で比べ、一致した候補の値を返す
  • ✅ match式はbreak不要で、一致しない場合はエラーになる
  • ✅ 1つの値を決めるならmatch式、複数行の処理を分けるならswitch文

次回は、同じ処理を繰り返す「for文・while文」について解説します。

次回は、決まった回数や条件を満たす間、同じ処理を繰り返すfor文とwhile文について解説予定です。

この記事が、少しでも誰かのお役に立てれば幸いです。

関連記事

当サイトの記事で使用したVBAなどのサンプルをDLできます

この記事のサンプルはありません!

ダウンロードページへは下のカードをクリックすればジャンプできます。
よろしければご利用ください!


【CSS】テキスト関連プロパティについて基本解説|Webの基礎


よかったらシェアしてね!
  • URLをコピーしました!
目次