Menu

PHPのmatch式:switchとの違い、match(true)の使い方

match ($x) { 1, 2 => 'low', default => 'other' } は値を厳密な===で比較し、最初に一致したアームの結果を返し、何にも一致しなければUnhandledMatchErrorを投げます。matchとswitchの違い、match(true)、enumと組み合わせたmatchを扱います。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

match ($value) { ... }は値をアームの一覧と厳密な===で比較し、最初に一致したアームの結果を返します。複数の値で1つのアームを共有でき、defaultが残りを受け止め、何にも一致しなければPHPはUnhandledMatchErrorを投げます。

閉じ波括弧のあとのセミコロンに注目してください。matchは1 + 2と同じく式なので、全体で1つの代入文になります。各アームは値 => 結果の形でカンマで区切り、最後のアームのあとのカンマも許されます。

1つのアームに複数の値

値をカンマで並べます。対象がそのどれかと同一(===)なら、そのアームが一致します。

この例のように関数からmatchを直接返すのが、いちばんよくある使い方です。

matchとswitchの違い

同じ対応関係を両方の書き方で、いちばん大きな違いである比較が表れる入力を使って書きます。switchは==を使うので、文字列"1"がcase 1に一致します。matchは===を使うので一致しません。

matchswitch
比較厳密な===ゆるい==
結果値を返す文で、何も返さない
フォールスルーしない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'のような配列の参照が必要です。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める