Laravel9 新機能の Enum route binding をサクッと確認しつつ、Explicit Binding に思いを馳せる
前書き
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