メジャーアップデートされたPHP8.0では、新しい処理分岐の式、matchが追加されました。
もともとswitch文がありますが、ちがいは結果を返すこと。戻り値として使えるし、そうなら当然、変数に結果を代入することもできます。
switchは『文』にたいしてmatchは『式』だからできること。
match式の使い方
match式はswitch文と似ていてかんたんなので、いきなりサンプルコードから行きましょう。
$val = 100;
$ret = match ($val) {
1 => 'one digits',
10 => 'two digits',
100 => 'triple digits',
1000 => 'quadruple digits',
};
var_dump($ret);
string(13) "triple digits"
これと同じことをswitch文で書くとこうなります。
$val = 100;
$ret = '';
switch ($val) {
case 1:
$ret = 'one digits';
break;
case 10:
$ret = 'two digits';
break;
case 100:
$ret = 'triple digits';
break;
case 1000:
$ret = 'quadruple digits';
break;
}
var_dump($ret);
string(13) "triple digits"
matchのほうがスッキリとしていいですね?
この2つのちがいをひとつひとつ見ていきましょう。
式と文のちがい
この2つのいちばんの違いは、switchは『文』に対して matchは『式』であることです。
文は中に複数の式や文を入れて処理を書けます。だからswitchでは各条件内に処理を書いて最後にbreak構文で終わってる。
一方、matchは式なので比較に一致したときの処理は書けません。書けるのは値のみ。
そこは文ではない証拠。switch文では条件に一致したときに複数の式が書け、処理が行なえます。
文は中かっこ({})でくくればそれで終わりですが、matchは式なので最後にセミコロン(;)が必要です。
'}' と '};' で終わり方がちがうところに注意。
当然ですが、matchは式なので変数に代入することができ、関数のパラメータ、戻り値にも指定できます。
$val = 10;
function test($match)
{
var_dump($match);
}
// パラメータに直接match式が渡せる
test(
match ($val) {
1 => 'one digits',
10 => 'two digits',
100 => 'triple digits',
1000 => 'quadruple digits',
}
);
string(10) "two digits"
function test($val)
{
// returnに直接match式が書ける
return match ($val) {
1 => 'one digits',
10 => 'two digits',
100 => 'triple digits',
1000 => 'quadruple digits',
};
}
$val = test(1000);
var_dump($val);
string(16) "quadruple digits"
switch文とのちがい。値の比較は厳密。
ここがswitchとmatchの最大のちがいと言ってもいいかもしれません。
switch文の値の比較はゆるい(==)ですが、match式は型と値で厳密に(===)比較します。
PHP8になってから、ほかのところでも比較の厳密化が進んでいますが、その一貫でしょう。
match式とswitch文を実行してみましょう。
match式の比較(厳密)
<?php
function match_test($val)
{
// returnに直接match式が書ける
return match ($val) {
1 => 'one digits',
10 => 'two digits',
100 => 'triple digits',
1000 => 'quadruple digits',
};
}
$val = match_test(100);
var_dump($val);
$val = match_test('100');
var_dump($val);
string(13) "triple digits"
PHP Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type string in /home/vagrant/php-test.php:6
Stack trace:
#0 /home/vagrant/php-test.php(17): match_test()
#1 {main}
thrown in /home/vagrant/php-test.php on line 6
match式では、値が一致しないとき黙ってスルーはしません。UnhandledMatchErrorの例外が発生します。
サンプルでは『文字列値のマッチはハンドルされていない。』のメッセージが出てますがひとつじゃないので注意が必要。
たとえば次の不一致ではメッセージがちがいます。
<?php
function match_test($val)
{
// returnに直接match式が書ける
return match ($val) {
1 => 'one digits',
10 => 'two digits',
100 => 'triple digits',
1000 => 'quadruple digits',
};
}
$val = match_test(53);
var_dump($val);
PHP Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type int in /home/vagrant/php-test.php:6
Stack trace:
#0 /home/vagrant/php-test.php(14): match_test()
#1 {main}
thrown in /home/vagrant/php-test.php on line 6
type 〇〇のところが変わるだけなんですけどね?
switch文の比較(ゆるい)
function switch_test($val)
{
$ret = 'value none';
switch ($val) {
case 1:
$ret = 'one digits';
break;
case 10:
$ret = 'two digits';
break;
case 100:
$ret = 'triple digits';
break;
case 1000:
$ret = 'quadruple digits';
break;
}
var_dump($ret);
}
switch_test(100);
switch_test('100');
switch_test(53);
string(13) "triple digits"
string(13) "triple digits"
string(10) "value none"
switch文は不一致であってもエラーにならずスルーされます。
match式に比べ、比較もゆるゆる、結果もゆるゆる、の曖昧さ満載です。
breakはいらない。
match式は上から順に比較していき、一致すればそこで式が終了し、そうじゃなければ次の比較を行うので、break; はいりません。
一方、switch文は、比較が一致しても次の比較を行います。だから比較の終わりには必ずbreak; を付ける慣習があるんですね?
とういか、break; を書かない理由がない。余計な処理が走るし。
そもそもbreakは文を抜けるためのキーワードです。式のmatchで使えるわけがない。
PHP公式ドキュメント