Laravel Enum 機能を試す
まえがき
Laravel 8.69~8.71辺りで、PHP8.1からの新機能の Enum への対応が始まっているので、それを試してみました。
PHP8.1 Enum の機能自体については、下記のリンクを辿って下さい。
PHP マニュアル 列挙型(Enum)
PHP 8.1: Enums(英語)
執筆時点の Laravel では、Validation、cast、Insert などで Enum がサポートされました。
Validation は、あまり試し甲斐がないので、以下では cast、そして最後に DB へ登録する所まで試してみました。
以下、参考リンク
[8.x] Add an Enum validation rule #39437
[8.x] Allow model attributes to be casted to/from an Enum #39315
[8.x] Accept enums for insert update and where #39492
[8.x] Enum casts accept backed values #39608
本題
ということで、まずはサンプル用 Enum ファイルを作成します。
app/Enums/UserStatus.php
<?php
namespace App\Enums;
enum UserStatus: int
{
case Pending = 1;
case Valid = 2;
case Locked = 3;
public function getStatus(): string
{
return match($this)
{
self::Pending => 'pending',
self::Valid => 'valid',
self::Locked => 'locked',
};
}
public function isLocked(): bool
{
return $this === self::Locked;
}
}
User用マイグレーションファイル
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
+ $table->unsignedTinyInteger('status');
$table->rememberToken();
$table->timestamps();
});
}
DBは、Enum型とかではなく、普通に tinyint にしています。
Userモデル
+use App\Enums\UserStatus;
class User extends Authenticatable
{
// 途中、略
protected $casts = [
'email_verified_at' => 'datetime',
+ 'status' => UserStatus::class,
];
web.php
Route::get('/', function () {
$user = new User();
$user->status = UserStatus::Pending; // まずはこれを試す。
// $user->status = 2;
// $user->status = '3';
// $user->status = 5;
dump($user->status === UserStatus::Pending);
dump($user->status === UserStatus::Valid);
dump($user->status->isLocked());
dd($user->status->getStatus());
});
と言うことで、「まずはこれを試す。」という箇所を試すと、以下の結果となります。
true
false
false
"pending"
続けて今後は、$user->status = 2; を有効化して試します。(Enumに数字や文字列を付加したりするのは、Backed Enum とか呼ばれたりしていますが…)
false
true
false
"valid"
こちらも大丈夫で、2番目が true になりました。
では今度は、$user->status = '3'; を有効化して試してみます、意図的に文字列にしていますが…
false
false
true
"locked"
こちらも問題無しで、3番目が true。
今度は、$user->status = 5; を試してみます。(5番は存在しない)
ValueError
5 is not a valid backing value for enum "App\Enums\UserStatus"
見事エラーになりました。
今度は、DBに保存してみます。とりあえず、以下の感じで。
Route::get('/', function () {
$user = new User();
$user->status = UserStatus::Pending;
$user->name = 'taro';
$user->email = 'aaa@example.net';
$user->password = bcrypt('aaaa');
$user->save();
return view('welcome');
});
画像無くてすいませんが、DBには1件無事保存され、'status' 欄には、1と登録されました。
雑感
いつかお世話になるかも知れません。
おかしな箇所等ありましたらコメント下さい。
Discussion