1. ホーム
  2. PHP

【PHP】match式の使い方|switchとの違いをわかりやすく解説

Share

値によって処理を分岐させたいとき、PHP では長らく switch 文が使われてきました。PHP 8.0 からは、より短く・安全に書ける match 式が追加されています。この記事では match の基本的な使い方と、switch との違い(戻り値・厳密比較・フォールスルーなし)を、具体的なコードで分かりやすく解説します。

match 式とは

match は、ひとつの値を複数の候補と比較し、一致した分岐の結果を値として返す式です。switch が「処理を実行する文」だったのに対し、match は「結果を返す式」なので、そのまま変数に代入できます。PHP 8.0 以降で使えます。

match.php
<?php
$status = 'shipping';

// 一致した分岐の値がそのまま $label に入る
$label = match ($status) {
    'pending'  => '支払い待ち',
    'shipping' => '発送準備中',
    'done'     => '完了',
};

echo $label; // 発送準備中

各分岐は 条件 => 返す値 の形で書き、カンマで区切ります。break は不要で、最後の分岐にもカンマを付けられます。

同じ処理を switch で書くと

同じことを switch で書くと、変数を用意して各 case で代入し、break を忘れずに書く必要があります。比べると match の簡潔さがよく分かります。

switch.php
<?php
$status = 'shipping';

switch ($status) {
    case 'pending':
        $label = '支払い待ち';
        break;
    case 'shipping':
        $label = '発送準備中';
        break;
    case 'done':
        $label = '完了';
        break;
}

echo $label; // 発送準備中

複数の値をまとめる・デフォルトを指定する

1つの分岐で複数の値を扱いたいときは、カンマで並べます。どれにも一致しないときの値は default で指定します。

match.php
<?php
$code = 404;

$message = match ($code) {
    200, 201, 204 => '成功',          // 複数の値をまとめる
    400, 404      => 'リクエストエラー',
    500           => 'サーバーエラー',
    default       => '不明なステータス', // どれにも一致しないとき
};

echo $message; // リクエストエラー

match と switch の違い

見た目が似ている2つですが、内部の動きにははっきりした違いがあります。順番に見ていきます。

厳密比較(===)で判定する

switch は緩やかな比較(==)で判定するため、型が違っても値が一致すれば通ってしまいます。一方 match は厳密比較(===)なので、値だけでなく型も一致する必要があります。これにより、意図しない一致を防げます。

compare.php
<?php
$value = '1'; // 文字列の "1"

// switch は == 比較なので、数値の 1 とも一致してしまう
switch ($value) {
    case 1:
        echo 'switch: 数値の1に一致'; // これが実行される
        break;
}

// match は === 比較。文字列 "1" と 数値 1 は一致しない
echo match ($value) {
    1       => '数値の1',
    '1'     => '文字列の1', // こちらに一致する
};
// 出力: 文字列の1

フォールスルーが無い

switchbreak を書き忘れると、次の case に処理が流れ込みます(フォールスルー)。これがバグの原因になりがちでした。match は一致した分岐だけを評価し、break という概念自体がありません。書き忘れによる事故が起きません。

一致しないと例外を投げる

match はどの分岐にも一致せず default も無いと、UnhandledMatchError という例外を投げます。switch のように「何にも一致せず黙って素通り」しないため、考慮漏れにすぐ気づけます。すべての値を網羅したいときはこの性質が役立ちます。

match.php
<?php
$status = 'unknown';

// default が無く、どれにも一致しないと例外
$label = match ($status) {
    'pending'  => '支払い待ち',
    'done'     => '完了',
};
// → UnhandledMatchError: Unhandled match case 'unknown'

主な違いを表にまとめます。

項目matchswitch
値を返す返す(代入できる)返さない
比較方法厳密比較(===緩やかな比較(==
break不要(フォールスルーなし)必要(書き忘れに注意)
未一致のとき例外を投げる(default で回避)何もせず素通り
利用可能バージョンPHP 8.0 以降すべて

match を使うときの注意点

分岐内に複数行の処理は書けない

match の各分岐は「式」を1つ書く場所です。switch のように複数行の処理を並べることはできません。複雑な処理が必要なら、関数に切り出して match ではその関数を呼ぶ形にすると整理できます。

match.php
<?php
// 処理は関数に切り出し、match では呼ぶだけにする
$result = match ($type) {
    'csv'  => exportCsv($data),
    'json' => exportJson($data),
    default => throw new InvalidArgumentException('未対応の形式'),
};

なお PHP 8.0 以降では throw も式として使えるため、上のように default で直接例外を投げることもできます。

条件で分岐したいときは match (true)

「値そのもの」ではなく「範囲」で分岐したいときは、match (true) と書くと各分岐に条件式を並べられます。最初に true になった分岐が採用されます。

match.php
<?php
$score = 82;

$grade = match (true) {
    $score >= 80 => 'A',
    $score >= 60 => 'B',
    default      => 'C',
};

echo $grade; // A

まとめ

match 式は、switch をより短く・安全にした分岐の書き方です。

  • 一致した分岐の結果を値として返すので、そのまま変数に代入できる
  • 厳密比較(===)で判定し、型の違いによる誤判定を防げる
  • break 不要でフォールスルーが無く、書き忘れの事故が起きない
  • 未一致で default も無いと例外になり、考慮漏れに気づける
  • 範囲で分岐したいときは match (true) が使える

「値を1つ受け取って、対応する値を返す」というシンプルな分岐なら、switch より match のほうが安全で読みやすくなります。PHP 8.0 以降の環境なら積極的に使ってみてください。詳しい仕様は PHP マニュアルの match も参考になります。