はじめに
Laravelでenumを扱おうとすると、よく出てくるのがこの三つのライブラリです。
- myclabs/php-enum
- [BenSampo/laravel-enum] (https://github.com/BenSampo/laravel-enum)
- [nasyrov/laravel-enums] (https://github.com/nasyrov/laravel-enums)
このうち、下二つはLaravel用のライブラリなので、親和性は高いと思うのですが、他PHPフレームワークを使う時に応用が効かないかなと思って、個人的にはphp-enumを推しています。(そもそもphp-enum以外は使ったことがないので、こっちのがいいぜ!という時は教えていただけるとありがたいです)
そういう訳で、laravelでphp-enumを使う時の個人的なベストプラクティスを紹介します。
ライブラリ | バージョン |
---|---|
laravel | 6.18 |
php-enum | 1.7 |
やり方
enumの定義
php-enumでは、MyCLabs\Enum\Enum
クラスを継承したクラスに、定数を定義することで、num値を定義します。このような感じです。
<?php
declare(strict_types=1);
namespace App\Enums;
use MyCLabs\Enum\Enum;
class RoleType extends Enum
{
public const SUPER_ADMIN = 'SUPER_ADMIN';
public const ADMIN = 'ADMIN';
public const USER = 'USER';
}
マイグレーションの作成
マイグレーションファイルを作る時は、Blueprint
のenum()
メソッドを使います。第二引数にはenumとして許可する値の配列を渡します。php-enumでは、values()
メソッドでそのenum内で定義されている値の配列を得ることができるので、この値を渡します。
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table): void {
$table->enum('role', RoleType::values());
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
}
}
モデルの定義
User
モデルにRoleType
を持たせる時、今の状態では$user->role
としてもRoleType
のインスタンスは取れず、DB上にあるスカラー値しか取れません。また、$user->role
にRoleType
をそのままセットすることもできず、スカラー値に変換してからセットする必要があります。
$role = RoleType::ADMIN();
$user = new User();
$user->role = $role->getValue();
$role = new Role($user->role);
// NG
// $user->role = $role;
プロパティの値を使う度に変換を行うのは手間なので、Laravelのミューテタ1を使います。
以下のようにgetRoleAttribute〇〇()
, setRoleAttribute〇〇()
メソッドを定義しておくことで、laravelがよしなに変換をしてくれます。
<?php
declare(strict_types=1);
namespace App\Models;
use App\Enums\AnaUserRole;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['role'];
public function getRoleAttribute(string $value): RoleType
{
return new Role($value);
}
public function setRoleAttribute(RoleType $role): void
{
$this->attributes['role'] = $role->getValue();
}
}
このようにかけます。
$role = RoleType::ADMIN();
$user = new User();
$user->role = $role;
// $roleはRoleTypeのインスタンス
$role = $user->role;
以上!