archtechx / enums
使PHP枚举更加可爱的小助手。
Requires
- php: ^8.1
Requires (Dev)
- larastan/larastan: ^2.4
- orchestra/testbench: ^8.0
- pestphp/pest: ^2.0
- pestphp/pest-plugin-laravel: ^2.0
README
PHP枚举辅助工具集合。
您可以在Twitter上了解更多关于原始想法的信息。
安装
需要PHP 8.1+。
composer require archtechx/enums
使用
可调用案例
此辅助工具允许您通过“调用”来获取支持枚举的值或纯枚举的名称——无论是静态的(MyEnum::FOO()
而不是MyEnum::FOO
),还是作为实例($enum()
)。
这样,您可以将枚举用作数组键
'statuses' => [ TaskStatus::INCOMPLETE() => ['some configuration'], TaskStatus::COMPLETED() => ['some configuration'], ],
或访问任何其他用例的底层原始数据
public function updateStatus(int $status): void; $task->updateStatus(TaskStatus::COMPLETED());
主要观点:这一切都不需要将->value
附加到所有内容上。
这种方法还有相当的IDE支持。您在输入时获得自动建议,然后只需附加()
MyEnum::FOO; // => MyEnum instance MyEnum::FOO(); // => 1
在您的枚举上应用特征
use ArchTech\Enums\InvokableCases; enum TaskStatus: int { use InvokableCases; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use InvokableCases; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用静态调用以获取原始值
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()); }
名称
此辅助工具返回枚举中案例的名称列表。
在您的枚举上应用特征
use ArchTech\Enums\Names; enum TaskStatus: int { use Names; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use Names; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用names()
方法
TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED'] Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
值
此辅助工具返回支持枚举的案例值列表,或纯枚举的案例名称列表(使此函数与纯枚举的::names()
功能等效)
在您的枚举上应用特征
use ArchTech\Enums\Values; enum TaskStatus: int { use Values; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use Values; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用values()
方法
TaskStatus::values(); // [0, 1, 2] Role::values(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
选项
此辅助工具返回支持枚举的案例名称和值的关联数组,或纯枚举的名称列表(使此函数与纯枚举的::names()
功能等效)。
在您的枚举上应用特征
use ArchTech\Enums\Options; enum TaskStatus: int { use Options; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use Options; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用options()
方法
TaskStatus::options(); // ['INCOMPLETE' => 0, 'COMPLETED' => 1, 'CANCELED' => 2] Role::options(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
stringOptions()
特性还添加了stringOptions()
方法,可用于生成枚举选项的便捷字符串表示形式
// First argument is the callback, second argument is glue // returns "INCOMPLETE => 0, COMPLETED => 1, CANCELED => 2" TaskStatus::stringOptions(fn ($name, $value) => "$name => $value", ', ');
对于纯枚举(非支持),使用名称代替$value
(这意味着$name
和$value
都是相同的)。
此方法的两个参数都是可选的,粘合剂默认为\n
,回调默认为生成HTML <option>
标签
// <option value="0">Incomplete</option> // <option value="1">Completed</option> // <option value="2">Canceled</option> TaskStatus::stringOptions(); // backed enum // <option value="ADMINISTRATOR">Administrator</option> // <option value="Subscriber">Subscriber</option> // <option value="GUEST">Guest</option> Role::stringOptions(); // pure enum
来自
此辅助工具向纯枚举添加from()
和tryFrom()
,向所有枚举添加fromName()
和tryFromName()
。
重要提示
BackedEnum
实例已经实现了自己的from()
和tryFrom()
方法,这些方法不会被此特性覆盖。在BackedEnum
中尝试覆盖这些方法会导致致命错误。- 纯枚举只有命名案例而没有值,因此
from()
和tryFrom()
方法在功能上等同于fromName()
和tryFromName()
在您的枚举上应用特征
use ArchTech\Enums\From; enum TaskStatus: int { use From; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use From; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用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
元数据
此特性允许您为枚举案例添加元数据。
在您的枚举上应用特征
use ArchTech\Enums\Metadata; use ArchTech\Enums\Meta\Meta; use App\Enums\MetaProperties\{Description, Color}; #[Meta(Description::class, Color::class)] enum TaskStatus: int { use Metadata; #[Description('Incomplete Task')] #[Color('red')] case INCOMPLETE = 0; #[Description('Completed Task')] #[Color('green')] case COMPLETED = 1; #[Description('Canceled Task')] #[Color('gray')] case CANCELED = 2; }
说明
Description
和Color
是用户空间类属性——元属性#[Meta]
调用启用了枚举上的这两个元属性- 每个案例都必须定义描述和颜色(在这个例子中)
访问元数据
TaskStatus::INCOMPLETE->description(); // 'Incomplete Task' TaskStatus::COMPLETED->color(); // 'green'
创建元属性
每个元属性(=用于案例的属性)都需要作为一个类存在。
#[Attribute] class Color extends MetaProperty {} #[Attribute] class Description extends MetaProperty {}
在类内部,您可以自定义一些功能。例如,您可能想要使用与类名派生的不同方法名(默认情况下,Description
变为 description()
)。为此,请在元属性上覆盖 method()
方法。
#[Attribute] class Description extends MetaProperty { public static function method(): string { return 'note'; } }
使用上述代码,案例的描述将可通过 TaskStatus::INCOMPLETE->note()
访问。
您还可以自定义传递的值。例如,要将颜色名称如 text-{$color}-500
包装起来,您需要添加以下 transform()
方法。
#[Attribute] class Color extends MetaProperty { protected function transform(mixed $value): mixed { return "text-{$value}-500"; } }
现在返回的颜色将被正确转换。
TaskStatus::COMPLETED->color(); // 'text-green-500'
您还可以添加一个 defaultValue()
方法,以指定如果案例未使用元属性,则应具有的值。这样,您可以在某些案例上应用属性,同时仍然可以在所有其他案例上获得可配置的默认值。
使用 fromMeta()
方法。
TaskStatus::fromMeta(Color::make('green')); // TaskStatus::COMPLETED TaskStatus::fromMeta(Color::make('blue')); // Error: ValueError
使用 tryFromMeta()
方法。
TaskStatus::tryFromMeta(Color::make('green')); // TaskStatus::COMPLETED TaskStatus::tryFromMeta(Color::make('blue')); // null
建议:使用注解和特性。
如果您想为元数据获取方法添加更好的IDE支持,可以使用 @method
注解。
/** * @method string description() * @method string color() */ #[Meta(Description::class, Color::class)] enum TaskStatus: int { use Metadata; #[Description('Incomplete Task')] #[Color('red')] case INCOMPLETE = 0; #[Description('Completed Task')] #[Color('green')] case COMPLETED = 1; #[Description('Canceled Task')] #[Color('gray')] case CANCELED = 2; }
如果您在多个枚举中使用相同的元属性,您可以创建一个包含此 @method
注解的专用特性。
可比较的
此特性允许您使用 is()
、isNot()
、in()
和 notIn()
比较枚举。
在您的枚举上应用特征
use ArchTech\Enums\Comparable; enum TaskStatus: int { use Comparable; case INCOMPLETE = 0; case COMPLETED = 1; case CANCELED = 2; } enum Role { use Comparable; case ADMINISTRATOR; case SUBSCRIBER; case GUEST; }
使用 is()
方法。
TaskStatus::INCOMPLETE->is(TaskStatus::INCOMPLETE); // true TaskStatus::INCOMPLETE->is(TaskStatus::COMPLETED); // false Role::ADMINISTRATOR->is(Role::ADMINISTRATOR); // true Role::ADMINISTRATOR->is(Role::NOBODY); // false
使用 isNot()
方法。
TaskStatus::INCOMPLETE->isNot(TaskStatus::INCOMPLETE); // false TaskStatus::INCOMPLETE->isNot(TaskStatus::COMPLETED); // true Role::ADMINISTRATOR->isNot(Role::ADMINISTRATOR); // false Role::ADMINISTRATOR->isNot(Role::NOBODY); // true
使用 in()
方法。
TaskStatus::INCOMPLETE->in([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // true TaskStatus::INCOMPLETE->in([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // false Role::ADMINISTRATOR->in([Role::ADMINISTRATOR, Role::GUEST]); // true Role::ADMINISTRATOR->in([Role::SUBSCRIBER, Role::GUEST]); // false
使用 notIn()
方法。
TaskStatus::INCOMPLETE->notIn([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // false TaskStatus::INCOMPLETE->notIn([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // true Role::ADMINISTRATOR->notIn([Role::ADMINISTRATOR, Role::GUEST]); // false Role::ADMINISTRATOR->notIn([Role::SUBSCRIBER, Role::GUEST]); // true
PHPStan
要协助PHPStan使用可调用的案例,可以将PHPStan扩展包含到您的 phpstan.neon
文件中。
includes: - ./vendor/archtechx/enums/extension.neon
开发
在本地运行所有检查。
./check
代码样式将由 php-cs-fixer 自动修复。