match ($value) { ... }は値をアームの一覧と厳密な===で比較し、最初に一致したアームの結果を返します。複数の値で1つのアームを共有でき、defaultが残りを受け止め、何にも一致しなければPHPはUnhandledMatchErrorを投げます。
閉じ波括弧のあとのセミコロンに注目してください。matchは1 + 2と同じく式なので、全体で1つの代入文になります。各アームは値 => 結果の形でカンマで区切り、最後のアームのあとのカンマも許されます。
1つのアームに複数の値
値をカンマで並べます。対象がそのどれかと同一(===)なら、そのアームが一致します。
この例のように関数からmatchを直接返すのが、いちばんよくある使い方です。
matchとswitchの違い
同じ対応関係を両方の書き方で、いちばん大きな違いである比較が表れる入力を使って書きます。switchは==を使うので、文字列"1"がcase 1に一致します。matchは===を使うので一致しません。
match | switch | |
|---|---|---|
| 比較 | 厳密な=== | ゆるい== |
| 結果 | 値を返す | 文で、何も返さない |
| フォールスルー | しない | breakまで続く |
| 複数の値 | 1, 2 => | case 1: case 2:を並べる |
| 一致なし | UnhandledMatchErrorを投げる | 何もしない |
| 分岐の中身 | 1つの式 | いくつでも文を書ける |
1つの値を別の値に変換するときはmatchを使います。分岐に複数の文が必要なときや、フォールスルーそのものが目的のときはswitchを使います。両方の例がswitchのページにあります。
UnhandledMatchError:どのアームにも一致しないとき
defaultのアームがなければ、何にも一致しない値は黙ってnullになるのではなくエラーになります。これは長所です。新しいステータスコードやタイプミスが、すり抜けずに大きな音を立てて失敗します。
PHPはPHP Fatal error: Uncaught UnhandledMatchError: Unhandled match case of type stringで止まります。開発用の設定(zend.exception_ignore_argsがオフ)では、代わりに値の名前が出ます:Unhandled match case 'XL'。default => 'other'を追加するか、未知の値が来うる場所でエラーをキャッチして直します。
範囲や条件にはmatch(true)
matchは対象を各アームと比較するので、対象がtrueなら、すべてのアームを条件にできます。最初にぴったりtrueと評価された条件が選ばれます。
このブロックには2つのポイントがあります。PHP 8以降throwは式なので、アームの結果にできます。また比較が厳密なので、各条件は本当のboolを返す必要があります。$name => ...のようなアームは、$nameが空でない文字列でもtrueには決して一致しません。評価されるのは一致したアームだけなので、throwが実行されるのは年齢が負のときだけです。
enumと組み合わせたmatch
matchとenumは相性がよく、enumのメソッドの中でmatch ($this)を使えば各ケースを値に対応させられます。enumそのものについてはPHPのenumを参照してください。
ここではあえてdefaultを書いていません。あとで誰かが5つ目のケースを追加したら、それに対してcolor()を呼ぶと、間違った色を返す代わりにエラーを投げます。
1つのアームで複数の文を実行する
アームに書けるのは1つの式なので、'save' => { ...; ... }は正しいPHPではありません。処理を関数に移し、アームから呼び出します。一致しなかったアームの関数が呼ばれることはありません。
$formatを'json'や'xml'に変えて、もう一度実行してみてください。
よくある質問
PHPのmatchとswitchの違いは何ですか?
matchは厳密な===で比較し、値を返し、次のアームへフォールスルーせず、1つのアームにカンマ区切りで複数の値を書け、どのアームにも一致しないとUnhandledMatchErrorを投げます。switchはゆるい==で比較し、何も返さない文で、breakがないとフォールスルーし、どのcaseにも一致しなければ黙って何もしません。
PHPのmatch式でどのアームにも一致しないとどうなりますか?
PHPはUnhandledMatchErrorを投げます。default => ...のアームを追加してほかのすべての値を処理するか、try { ... } catch (\UnhandledMatchError $e) { ... }でエラーをキャッチします。
PHPのmatchで「より大きい」のような条件を使うには?
trueに対してmatchします:match (true) { $age < 13 => 'child', $age < 18 => 'teen', default => 'adult' }。各アームが条件になり、最初にぴったりtrueになったものが選ばれます。
PHPのmatchの1つのアームで複数の文を実行できますか?
できません。各アームは1つの式です。文は関数やメソッドにまとめ、アームからそれを呼び出します。たとえば'export' => exportCsv($rows)です。
matchはどのバージョンのPHPで追加されましたか?
PHP 8.0です。PHP 7で同じロジックを書くには、switch文か、$labels[$status] ?? 'Unknown'のような配列の参照が必要です。