値によって処理を分岐させたいとき、PHP では長らく switch 文が使われてきました。PHP 8.0 からは、より短く・安全に書ける match 式が追加されています。この記事では match の基本的な使い方と、switch との違い(戻り値・厳密比較・フォールスルーなし)を、具体的なコードで分かりやすく解説します。
目次
match 式とは
match は、ひとつの値を複数の候補と比較し、一致した分岐の結果を値として返す式です。switch が「処理を実行する文」だったのに対し、match は「結果を返す式」なので、そのまま変数に代入できます。PHP 8.0 以降で使えます。
<?php
$status = 'shipping';
// 一致した分岐の値がそのまま $label に入る
$label = match ($status) {
'pending' => '支払い待ち',
'shipping' => '発送準備中',
'done' => '完了',
};
echo $label; // 発送準備中
各分岐は 条件 => 返す値 の形で書き、カンマで区切ります。break は不要で、最後の分岐にもカンマを付けられます。
同じ処理を switch で書くと
同じことを switch で書くと、変数を用意して各 case で代入し、break を忘れずに書く必要があります。比べると match の簡潔さがよく分かります。
<?php
$status = 'shipping';
switch ($status) {
case 'pending':
$label = '支払い待ち';
break;
case 'shipping':
$label = '発送準備中';
break;
case 'done':
$label = '完了';
break;
}
echo $label; // 発送準備中
複数の値をまとめる・デフォルトを指定する
1つの分岐で複数の値を扱いたいときは、カンマで並べます。どれにも一致しないときの値は default で指定します。
<?php
$code = 404;
$message = match ($code) {
200, 201, 204 => '成功', // 複数の値をまとめる
400, 404 => 'リクエストエラー',
500 => 'サーバーエラー',
default => '不明なステータス', // どれにも一致しないとき
};
echo $message; // リクエストエラー
match と switch の違い
見た目が似ている2つですが、内部の動きにははっきりした違いがあります。順番に見ていきます。
厳密比較(===)で判定する
switch は緩やかな比較(==)で判定するため、型が違っても値が一致すれば通ってしまいます。一方 match は厳密比較(===)なので、値だけでなく型も一致する必要があります。これにより、意図しない一致を防げます。
<?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
フォールスルーが無い
switch は break を書き忘れると、次の case に処理が流れ込みます(フォールスルー)。これがバグの原因になりがちでした。match は一致した分岐だけを評価し、break という概念自体がありません。書き忘れによる事故が起きません。
一致しないと例外を投げる
match はどの分岐にも一致せず default も無いと、UnhandledMatchError という例外を投げます。switch のように「何にも一致せず黙って素通り」しないため、考慮漏れにすぐ気づけます。すべての値を網羅したいときはこの性質が役立ちます。
<?php
$status = 'unknown';
// default が無く、どれにも一致しないと例外
$label = match ($status) {
'pending' => '支払い待ち',
'done' => '完了',
};
// → UnhandledMatchError: Unhandled match case 'unknown'
主な違いを表にまとめます。
| 項目 | match 式 | switch 文 |
|---|---|---|
| 値を返す | 返す(代入できる) | 返さない |
| 比較方法 | 厳密比較(===) | 緩やかな比較(==) |
break | 不要(フォールスルーなし) | 必要(書き忘れに注意) |
| 未一致のとき | 例外を投げる(default で回避) | 何もせず素通り |
| 利用可能バージョン | PHP 8.0 以降 | すべて |
match を使うときの注意点
分岐内に複数行の処理は書けない
match の各分岐は「式」を1つ書く場所です。switch のように複数行の処理を並べることはできません。複雑な処理が必要なら、関数に切り出して match ではその関数を呼ぶ形にすると整理できます。
<?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 になった分岐が採用されます。
<?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 も参考になります。