🔭

Laravel9 新機能の Enum route binding をサクッと確認しつつ、Explicit Binding に思いを馳せる

2022/01/07に公開

前書き

Laravel9 のリリースも近づいて来ましたが、Laravel9 に新たに加わった機能の Enum route binding を試してみます。

(注)まだ正式リリースされていませんので、どんでん返しがあるかも分かりません。(たぶん大丈夫)

参考: [9.x] Adds implicit Enum route binding #40281

Laravel9の開発版は、以下の感じインストールできます。

composer create-project --prefer-dist laravel/laravel laravel-9-dev dev-develop
(laravel-9-dev の箇所はプロジェクト名です)

なお、Enum は、PHP8.1 からの新機能です。

本題

プルリクを参考に、以下の感じで作ってみます。

app/Enums/UserStatus.php

<?php

namespace App\Enums;

enum UserStatus: string
{
    case Guest = 'guest';
    case Valid = 'valid';
    case Locked = 'locked';

    public function greeting(): string
    {
        return 'ようこそ、'.$this->value.'さん';
    }
}

web.php

use App\Enums\UserStatus;

Route::get('/users/{status}', function (UserStatus $status) {
    return $status->greeting();
});

これで、
http://localhost/users/locked とかでアクセスすると、以下のように出力されます。

ようこそ、lockedさん

valid や locked の時は、想像通りの出力になります。

存在しない hoge とかでアクセスすると、http://localhost/users/hoge
「404 NOT FOUND」の画面が出力されます。

Enum をフル活用される方には、これは便利な機能かと思います。
なお、string 型を返す Backed Enum でのみ利用可となっています。

ところで

やや蚊帳の外に置かれている感のある Explicit Binding 機能ですが、これも結構ポテンシャル持っているんですよね。特に、Route::bind()
「Route model binding」という名前が先行しているので、Eloquent モデルでないといけないと思いがちですが、それに捕らわれず、何を返してもいいんですね。

例えば、Laravel9 ではなくても、Explicit Binding 機能 を使って、上記を実現する事は可能です。以下みたいな感じです。

web.php

Route::get('/users2/{status2}', function ($status2) {
    return $status2->greeting();
});

RouteServiceProvider

use App\Enums\UserStatus;

class RouteServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Route::bind('status2', function ($value) {
            abort_if(
                is_null($status = UserStatus::tryFrom($value)), 404
            );

            return $status;
        });
    }
}

これで、
http://localhost/users2/locked とかでアクセスすると、先と同じ感じで出力されますし、/users2/hoge の場合は、「404 NOT FOUND」となります。

雑感

Explicit Binding、時折使えます。濫用はしない方が良さそうですが。

間違い等ありましたら、コメントお願いします。

Discussion