laravel的枚举助手——基于php8.1的枚举特性
基于php8.1枚举特性的laravel的枚举助手。
Github (喜欢这个项目点个 star 吧,灰常感谢~)
安装
你可以通过composer安装软件包:
composer require biiiiiigmonster/laravel-enum
使用
将Trait类应用于枚举:
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
// 值枚举
enum TaskStatus: int
{
use EnumTraits;
case INCOMPLETE = 0;
case COMPLETED = 1;
case CANCELED = 2;
}
// 纯枚举
enum Role
{
use EnumTraits;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
Invokable
此助手允许你通过静态方法MyEnum::FOO()
或者枚举实例调用$enum()
的方式,来获取值枚举的值或纯枚举的名。
这样,就可以直接使用枚举作为数组键:
'statuses' => [
TaskStatus::INCOMPLETE() => ['some configuration'],
TaskStatus::COMPLETED() => ['other configuration'],
],
或者可以直接调用任何其他case:
public function updateStatus(int $status): void;
$task->updateStatus(TaskStatus::COMPLETED());
要点:这一切都无需追加->value
:
TaskStatus::CANCELED; // => TaskStatus 实例
TaskStatus::CANCELED(); // => 2
使用静态调用方式获取基础值
TaskStatus::INCOMPLETE(); // 0
TaskStatus::COMPLETED(); // 1
TaskStatus::CANCELED(); // 2
Role::ADMINISTRATOR(); // 'ADMINISTRATOR'
Role::SUBSCRIBER(); // 'SUBSCRIBER'
Role::GUEST(); // 'GUEST'
调用实例方式获取基础值
public function updateStatus(TaskStatus $status, Role $role)
{
$this->record->setStatus($status(), $role());
}
增强
助手为你提供了许多静态方法来增强枚举使用的体验。
Names
返回枚举中所有case ->name
属性值的列表数组。
TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
Values
返回枚举中所有case ->value
属性值的列表数组,如果在纯枚举中调用,它将与::names()
结果一样。
TaskStatus::values(); // [0, 1, 2]
Role::values(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
Options
返回一个数组,该数组的键是枚举中每一个case实例()
调用值,具有唯一性;而该数组的值是枚举中每一个case实例的->label()
返回值。此方法能够轻松的将一个枚举转化成下拉框中的候选项:
TaskStatus::options();
/*
[
0 => 'Incomplete',
1 => 'Completed',
2 => 'Canceled'
]
*/
Role::options();
/*
[
'ADMINISTRATOR' => 'Administrator',
'SUBSCRIBER' => 'Subscriber',
'GUEST' => 'Guest'
]
*/
Tables
返回一个列表数组,他们当中的每一项都是一个case实例的映射数组,如果实例中有添加Meta
注解,那么case实例的映射数组中将包含更多内容。
TaskStatus::tables();
/*
[
['name' => 'INCOMPLETE', 'value' => 0],
['name' => 'COMPLETED', 'value' => 1],
['name' => 'CANCELED', 'value' => 2]
]
*/
Role::tables();
/*
[
['name' => 'ADMINISTRATOR'],
['name' => 'SUBSCRIBER'],
['name' => 'GUEST']
]
*/
From
此助手为纯枚举中添加了from()
和tryFrom()
方法,并且添加了fromName()
和tryFromName()
公共方法。
重要提示:
值枚举
实例已经实现了源生的from()
和tryFrom()
方法,这些方法不会被此Trait覆盖,试图重写值枚举
中的这些方法会导致致命错误。纯枚举
只有命名case而没有值,因此from()
和tryFrom()
方法在功能上等效于fromName()
或tryFromName()
。
使用from()
方法
Role::from('ADMINISTRATOR'); // Role::ADMINISTRATOR
Role::from('NOBODY'); // Error: ValueError
使用tryFrom()
方法
Role::tryFrom('GUEST'); // Role::GUEST
Role::tryFrom('NEVER'); // null
使用fromName()
方法
TaskStatus::fromName('INCOMPLETE'); // TaskStatus::INCOMPLETE
TaskStatus::fromName('MISSING'); // Error: ValueError
Role::fromName('SUBSCRIBER'); // Role::SUBSCRIBER
Role::fromName('HACKER'); // Error: ValueError
使用tryFromName()
方法
TaskStatus::tryFromName('COMPLETED'); // TaskStatus::COMPLETED
TaskStatus::tryFromName('NOTHING'); // null
Role::tryFromName('GUEST'); // Role::GUEST
Role::tryFromName('TESTER'); // null
Random
返回一个随机的case。
TaskStatus::random(); // TaskStatus::COMPLETED
Role::random(); // Role::GUEST
Meta
此功能允许你将Meta数据添加到枚举case中,它是通过php注解的方式使用的。
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use App\Enums\Metas\{Description, Color};
enum TaskStatus: int
{
use EnumTraits;
#[Description('Incomplete Task')] #[Color('red')]
case INCOMPLETE = 0;
#[Description('Completed Task')] #[Color('green')]
case COMPLETED = 1;
#[Description('Canceled Task')] #[Color('gray')]
case CANCELED = 2;
}
创建Meta注解
每个Meta注解都是作为一个类存在的,它必须继承BiiiiiigMonster\LaravelEnum\Concerns\Meta
类。
use BiiiiiigMonster\LaravelEnum\Concerns\Meta;
#[Attribute]
class Color extends Meta {}
#[Attribute]
class Description extends Meta {}
在注解中,你可以自定义一些内容。例如,你可能希望使用与从类名派生的方法名称不同的方法名称(默认情况下,Description
变为description()
),可以在注解中定义alias
静态属性:
#[Attribute]
class Description extends Meta
{
public static string $alias = 'note';
}
基于上面的改动,case的->description()
将可以作为->note()
访问。
你还可以自定义传递的Meta注解值。例如,要包装像text-{$color}-500
这样的颜色名称,你需要添加以下transform()
方法:
#[Attribute]
class Color extends Meta
{
protected function transform(mixed $value): string
{
return "text-{$value}-500";
}
}
现在,返回的颜色将被正确转换:
TaskStatus::COMPLETED->color(); // 'text-green-500'
访问Meta数据
通过访问注解类方法名称,可以获得meta值:
TaskStatus::INCOMPLETE->description(); // 'Incomplete Task'
TaskStatus::COMPLETED->color(); // 'green'
此外,::tables()
静态方法可以返回每个实例上的所有Meta注解映射。
$tables = TaskStatus::tables();
// $tables
[
[
'name' => 'INCOMPLETE',
'value' => 0,
'description' => 'Incomplete Task',
'color' => 'red'
],
[
'name' => 'COMPLETED',
'value' => 1,
'description' => 'Completed Task',
'color' => 'green'
],
[
'name' => 'CANCELED',
'value' => 2,
'description' => 'Canceled Task',
'color' => 'gray'
]
]
使用fromMeta()
方法
同样,你也可以通过Meta实例获得枚举case实例:
$green = Color::make('green');// new Color('green');
$blue = Color::make('blue');// new Color('blue');
TaskStatus::fromMeta($green); // TaskStatus::COMPLETED
TaskStatus::fromMeta($blue); // Error: ValueError
使用tryFromMeta()
方法
TaskStatus::tryFromMeta($green); // TaskStatus::COMPLETED
TaskStatus::tryFromMeta($blue); // null
表单验证
通常,我们需要将应用程序的传入数据限制在指定的枚举中,laravel提供了基本规则,但在这里我们已经完善了它。
数组语法验证
你可以对规则使用array
语法。
Enum
验证参数是否是给定枚举的实例,它类似于Enum
规则,并且可以支持纯枚举。
use BiiiiiigMonster\LaravelEnum\Rules\Enum;
public function store(Request $request)
{
$this->validate($request, [
'status' => ['required', new Enum(TaskStatus::class)],
'role' => ['required', new Enum(Role::class)],
]);
}
EnumMeta
此外,验证参数是否是给定枚举中给定Meta的实例。
use BiiiiiigMonster\LaravelEnum\Rules\EnumMeta;
public function store(Request $request)
{
$this->validate($request, [
'color' => ['required', new EnumMeta(TaskStatus::class, Color::class)],
]);
}
EnumMeta
规则有两个参数,第一个为给定枚举,第二个为给定Meta注解类,如果参数名称和Meta方法名称相同,可以省略第二个参数:
'color' => ['required', new EnumMeta(TaskStatus::class)],
管道语法验证
你也可以对规则使用pipe
语法。
- enumerate: enum_class
- enum_meta: enum_class,[meta_attribute]
'status' => 'required|enumerate:' . TaskStatus::class,
'color' => 'required|enum_meta:' . TaskStatus::class . ',' . Color::class,
验证消息
如果需要,您可以在验证失败时修改错误消息。运行以下命令将语言文件发布到lang
文件夹:
php artisan vendor:publish --provider="BiiiiiigMonster\LaravelEnum\EnumServiceProvider" --tag="translations"
本地化
标签
枚举case是描述性的,我们为此添加了翻译功能。你可以使用Laravel内置的本地化功能来翻译枚举实例的->label()
方法返回的字符串。
为你支持的每种语言添加一个新的enums.php
翻译文件。在本例中,有一个用于英语,一个用于西班牙语:
// lang/en/enums.php
<?php declare(strict_types=1);
use App\Enums\TaskStatus;
return [
TaskStatus::class => [
TaskStatus::INCOMPLETE() => 'Incomplete',
TaskStatus::COMPLETED() => 'Completed',
TaskStatus::CANCELED() => 'Canceled',
],
];
// lang/es/enums.php
<?php declare(strict_types=1);
use App\Enums\TaskStatus;
return [
TaskStatus::class => [
TaskStatus::INCOMPLETE() => 'Incompleto',
TaskStatus::COMPLETED() => 'Completo',
TaskStatus::CANCELED() => 'Cancelación',
],
];
现在,你只需要确保你的枚举实现了Localized
接口,如下所示:
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use BiiiiiigMonster\LaravelEnum\Contracts\Localizable;
enum TaskStatus: int implements Localizable
{
use EnumTraits;
// ...
}
->label()
方法现在将在本地化文件中查找该翻译字符串:
// en/enums.php
TaskStatus::CANCELED->label();// 'Canceled'
// es/enums.php
TaskStatus::CANCELED->label();// 'Cancelación'
并且::options()
静态方法返回的数组的值也被本地化:
// en/enums.php
TaskStatus::options();// [0 => 'Incomplete', 1 => 'Completed', 2 => 'Canceled']
// es/enums.php
TaskStatus::options();// [0 => 'Incompleto', 1 => 'Completo', 2 => 'Cancelación']
命令行
如果你希望IDE自动完成代码提示,你可以通过artisan命令生成PHPDoc注释。
默认情况下,app/Enums
路径中的所有枚举都将生成注释(你可以通过--folder
来指定文件夹路径):
php artisan enum:phpdoc
此外,还可以通过指定枚举类名为单个类生成注释:
php artisan enum:phpdoc "App\Enums\TaskStatus"
use BiiiiiigMonster\LaravelEnum\Concerns\EnumTraits;
use App\Enums\Metas\{Description, Color};
/**
* @method static int INCOMPLETE()
* @method static int COMPLETED()
* @method static int CANCELED()
* @method mixed description()
* @method mixed color()
*/
enum TaskStatus: int
{
use EnumTraits;
// ...
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
非常不错
点赞。
very nice