datomatic / laravel-enum-helper
简单的、有偏见的、框架无关的PHP 8.1枚举助手,用于Laravel
Requires
- php: ^8.1
- composer/class-map-generator: ^1.0
- datomatic/enum-helper: ^1.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0
- illuminate/translation: ^8.0|^9.0|^10.0|^11.0
- jawira/case-converter: ^3.5
- laminas/laminas-code: ^4.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- orchestra/testbench: ^6.23|^7.0|^9.0
- pestphp/pest: ^1.21|^2.34
- pestphp/pest-plugin-laravel: ^1.2|^2.3
- phpstan/phpstan: ^1.7
README
Laravel 枚举助手
这是基于 Laravel 框架的 datomatic/enum-helper 包的扩展。该包包含一个 LaravelEnumHelper 特性,它扩展了 EnumInvokable、EnumFroms、EnumNames、EnumValues、EnumEquality、EnumDescription,并添加了动态方法以返回翻译或“属性”方法和相关辅助方法。
您可以将它视为一个完全动态的 EnumDescription 特性。
因此,您可以定义一个自定义 method() 并拥有以下函数:[method]s()、[method]sByName()、[method]sByValue()。例如,使用 color(),您将获得 colors()、colorsByName()、colorsByValue() 方法。
酷的地方在于,您还可以避免编写方法,只编写翻译。例如,您可以通过在 enums.php 中仅编写翻译来定义属性 excerpt(参见下面的说明),并获得 excerpt()、excerpts()、excerptsByName()、excerptsByValue() 方法。
该包使用 Laravel Pluralizer 组件 来获取要调用的单数方法或进行翻译。
相关包
- datomatic/laravel-enum-collections 如果您需要在单个字段中保存和交互多个枚举值。
- datomatic/nova-enum-field 如果您正在使用 Laravel Nova,此包添加了 PHP 8.1 的
enum、EnumDescription和LaravelEnumHelper特性支持,并附带 Nova Select 和 Nova Boolean 过滤器。
enum-helper 基础包总结
您可以在 其存储库 上看到 datomatic/enum-helper 的详细信息,这是一个总结。
- 可调用情况:通过静态调用枚举值来获取枚举值
- 按名称或值构造枚举:为所有枚举提供
from()、tryFrom()、fromName()、tryFromName() - 枚举检查:提供
isPure()、isBacked()、has()、hasName()、hasValue()方法 - 枚举相等性:提供
is()、isNot()、in()、notIn()方法 - 名称:提供获取案例名称列表的方法(
names()、namesByValue()) - 值:提供获取案例值列表的方法(
values()、valuesByName()) - 唯一 ID:从实例或标识符获取唯一标识符(
uniqueId()、fromUniqueId()) - 描述和翻译:为枚举添加描述(可选翻译)(
description()、descriptions()、descriptionsByName()、descriptionsByValue())
安装
需要 Laravel 8 或以上版本和 PHP 8.1+。
composer require datomatic/laravel-enum-helper
使用方法
您可以通过使用 LaravelEnumHelper 特性来简单地使用此功能。
use Datomatic\LaravelEnumHelper\LaravelEnumHelper; // Pure enum enum Status { use LaravelEnumHelper; case PENDING; case ACCEPTED; case DISCARDED; case NO_RESPONSE; public function color(): string { return match ($this) { self::PENDING => '#000000', self::ACCEPTED => '#0000FF', self::DISCARDED => '#FF0000', self::NO_RESPONSE => '#FFFFFF', }; } } // BackedEnum enum StatusString { use LaravelEnumHelper; case PENDING = 'P'; case ACCEPTED = 'A'; case DISCARDED = 'D'; case NO_RESPONSE = 'N'; // or public function color(?string $lang = null): string public function color(): string { ... }
之后,您可以定义一个自定义的 "属性" 方法,如 color() 或 color(?string $lang = null),或者定义翻译。
翻译
使用此特性,有两种方式来管理翻译字符串。
使用简短键
语言字符串可以存储在 lang 目录下的 enums.php 文件中。在此目录中,可能存在每个由应用程序支持的子目录。
/lang
/en
enums.php
/it
enums.php
所有语言文件都返回一个键字符串数组。数组有3级
- 第一级键:枚举的完整类名
- 第二级键:要翻译的属性名
- 第三级键:枚举情况的名字/值。
默认属性是 description,因此如果您只使用该属性,则可以使用仅两级数组的结构。
// /lang/it/enums.php return [ // If you need to translate just the description property Status::class => [ Status::PENDING() => 'In attesa', // using invokable trait functionality 'ACCEPTED' => 'Accettato', // using the name of pure enum case 'DISCARDED' => 'Rifiutato', 'NO_RESPONSE' => 'Nessuna Risposta', ], // If you need to translate multiple properties (e.g. description, excerpt) StatusString::class => [ 'description' => [ // using invokable trait functionality StatusString::PENDING() => 'In attesa', StatusString::ACCEPTED() => 'Accettato', ... ], 'excerpt' => [ // using the value of BackedEnum case "P" => 'In attesa', "A" => 'Accettato', ...
使用翻译字符串作为键
语言字符串以 JSON 文件的形式存储在 lang 目录中(例如,lang/it.json)。在此示例中,已翻译 description 属性。
{
"enums.Namespace\\StatusString.description.P": "In attesa",
"...":"..."
}
但是,如果您想使用这种方式,您只需在枚举类上定义该方法即可,如 description 方法。
public function description(?string $lang = null): string { return match ($this) { self::PENDING => __('Await decision', $lang), self::ACCEPTED => __('Recognized valid', $lang), self::DISCARDED => __('No longer useful', $lang), self::NO_RESPONSE => __('No response', $lang), };
[property]() 方法
此动态方法尝试在枚举上解析 property() 方法。
如果不存在该方法,则尝试使用框架的翻译函数 __("enums.Namespace\EnumClass.property.CASE_NAME") 将实例值翻译。
因为默认属性是 description,如果没有翻译该属性,将使用人类化的情况名称作为后备。对于其他属性,如果不存在翻译,则包抛出 TranslationMissing 异常。
静态 [property]s() 方法
此动态方法获取枚举返回的案例 property() 列表。方法名称是属性的复数形式,因此如果您使用 property,则将是 properties()。
StatusString::descriptions(); // ['Await decision','Recognized valid','No longer useful','No response'] StatusString::colors(); // ['#000000','#0000FF','#FF0000','#FFFFFF'] // Subset StatusString::descriptions([StatusString::ACCEPTED, StatusString::NO_RESPONSE]); // ['Recognized valid','No response'] StatusString::colors([StatusString::ACCEPTED, StatusString::NO_RESPONSE]); // ['#0000FF','#FFFFFF'] // Forcing language Status::descriptions(null, 'it'); // 🇮🇹 ['In attesa','Accettato','Rifiutato','Nessuna Risposta'] StatusString::colors(null, 'it'); // ['#000000','#0000FF','#FF0000','#FFFFFF'] // Subset and language Status::descriptions([Status::NO_RESPONSE, Status::DISCARDED], 'it'); // 🇮🇹 ['Nessuna Risposta', 'Rifiutato'] StatusString::colors([StatusString::ACCEPTED, StatusString::NO_RESPONSE], 'it'); // ['#0000FF','#FFFFFF']
静态 [property]sByName() 方法
此动态方法返回一个关联数组 [case name => property() 结果]。方法名称是属性的复数形式,因此如果您使用 property,则将是 propertiesByName()。
StatusString::descriptionsByName(); // ['PENDING' => 'Await decision', 'ACCEPTED' => 'Recognized valid',... StatusString::colorsByName(); // ['PENDING' => '#000000','ACCEPTED' => '#0000FF',... Status::descriptionsByName(); // ['PENDING' => 'Await decision', 'ACCEPTED' => 'Recognized valid',... // Subset StatusString::descriptionsByName([StatusString::DISCARDED, StatusString::ACCEPTED]); // ['DISCARDED' => 'No longer useful', 'ACCEPTED' => 'Recognized valid'] Status::descriptionsByName([[Status::PENDING, Status::DISCARDED]); // ['PENDING' => 'Await decision', 'DISCARDED' => 'No longer useful'] // Forcing language StatusString::descriptionsByName(null, 'it'); // 🇮🇹 ['P' => 'In attesa','A' => 'Accettato',... // Subset and language Status::descriptionsByName([Status::DISCARDED, Status::NO_RESPONSE], 'it'); // 🇮🇹 ['DISCARDED' => 'Rifiutato','NO_RESPONSE' => 'Nessuna Risposta',...
静态 [property]sByValue() 方法
此动态方法返回一个关联数组 [case value => property() 结果] 在 BackedEnum 上,[case name => property() 结果] 否则。方法名称是属性的复数形式,因此如果您使用 property,则将是 propertiesByValue()。
Status::descriptionsByValue(); // ['PENDING' => 'Await decision', 'ACCEPTED' => 'Recognized valid',... StatusString::descriptionsByValue(); // ['P' => 'Await decision', 'A' => 'Recognized valid',... StatusString::colorsByValue(); // ['P' => '#000000','A' => '#0000FF',... // Subset Status::descriptionsByValue([Status::PENDING, Status::DISCARDED]); // ['PENDING' => 'Await decision', 'DISCARDED' => 'No longer useful'] StatusString::descriptionsByValue([StatusString::DISCARDED, StatusString::ACCEPTED]); // ['D' => 'No longer useful', 'A' => 'Recognized valid'] StatusString::colorsByValue([[Status::PENDING, Status::DISCARDED]); // ['P' => '#000000', 'D' => '#FF0000'] // Forcing language StatusString::descriptionsByValue(null, 'it'); // 🇮🇹 ['P' => 'In attesa','A' => 'Accettato',... // Subset and language Status::descriptionsByValue([StatusString::DISCARDED, StatusString::NO_RESPONSE], 'it'); // 🇮🇹 ['DISCARDED' => 'Rifiutato','NO_RESPONSE' => 'Nessuna Risposta',...

