巷ではLaravel 10がリリースされ賑わっていますが、最近私が担当した案件はL9へのUpgradeです。
いつもの様にLaravel Shiftが出してくれるPull Requestを眺めていると、見慣れない記法が出てきました。
調べてみるとPHP8.0から導入されてた記法でした。

PHP8.0がリリースされて間も無くキャッチアップしたはずなのですが、全く記憶にありません。
ということで、再度PHP8.0から導入された機能を復習しました。
いくつか取り入れたい記法を見つけたのでご紹介します。
今回はmatch式です。

match式

公式マニュアルより抜粋。

$return_value = match (制約式) {
    単一の条件式 => 返却式,
    条件式1, 条件式2 => 返却式,
};

match式はswitch文と似ています。条件とそれにmatchした場合に返却する値を指定します。

switch文と異なり条件にmatchしているか比較する際に“==”ではなく“===”が用いられます。

つまり、

// switch文
$num = '0';

switch ($num) {
    case 0:
        echo "integer zero";
        break;
    case '0':
        echo "string zero";
}

>> integer zero

// match式
$matched = match ($num) {
    0 => "integer zero",
    '0' => "string zero",
};

echo $matched;

>> string zero

因みにmatchは式なので末尾のセミコロンを忘れないように注意です!

複数の条件で同じ値を返す場合やいずれの条件にも当てはまらなかった場合(デフォルト)の書き方はswitch文と似ているので理解しやすいです。

$matched = match ($trafficSignal) {
    'blue', 'green' => 'go',    // blue, green のいずれかなら
    'yellow' => 'caution',
    'red' => 'stop',
    default => 'nothing to do'    // いずれの条件にもmatchしないなら
};

Laravel9から学ぶ活用方法

Laravel9からはPHP8.0以上が要件となった事で、ソースコード内でも色々な箇所で活用されている様です。
どの様な使い方をしているのでしょうか?

例えば、Handler.php にて例外がスローされた際のレスポンスをレンダリングしている箇所では

    public function render($request, Throwable $e)
    {
        〜〜省略〜〜

        return match (true) {
            $e instanceof HttpResponseException => $e->getResponse(),
            $e instanceof AuthenticationException => $this->unauthenticated($request, $e),
            $e instanceof ValidationException => $this->convertValidationExceptionToResponse($e, $request),
            default => $this->renderExceptionResponse($request, $e),
        };
    }

前の段落で扱ったサンプルコードではいずれも制約式に変数を渡していましたが、こちらはtrueを指定しています。
そして、上から順番にtrueを返す条件式が無いかチェックしていきます。

もし、$eHttpResponseExceptionのインスタンスなら、$e->getResponse()を実行して結果を返却。
それ以外でもし、$eAuthenticationExceptionのインスタンスなら、$this->unauthenticated($request, $e)を実行して結果を返却。
それ以外でもし、、、(以下省略)

これはつまり、従来は if ... elseif ... で書いていたパターンですね。

実際、Laravel 8まではif文で書かれていた様です。

    public function render($request, Throwable $e)
    {
        〜〜省略〜〜

        if ($e instanceof HttpResponseException) {
            return $e->getResponse();
        } elseif ($e instanceof AuthenticationException) {
            return $this->unauthenticated($request, $e);
        } elseif ($e instanceof ValidationException) {
            return $this->convertValidationExceptionToResponse($e, $request);
        }

        return $this->shouldReturnJson($request, $e)
                    ? $this->prepareJsonResponse($request, $e)
                    : $this->prepareResponse($request, $e);
    }

if ... elseif ... よりもmatch式を使った書き方の方が行数も少ないし、随分シンプルな印象を受けます。
今後の開発時に活用していきたいと思いました。

By hikaru