苏莱曼诺夫 / laravel-enum-helper
简单的、有偏见的、框架无关的 PHP 8.1 枚举辅助器,适用于 Laravel
Requires
- php: ^8.1
- composer/class-map-generator: ^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
- suleymanozev/enum-helper: ^1.0
Requires (Dev)
- laravel/pint: ^v1.13
- orchestra/testbench: ^6.23|^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.2
- phpstan/phpstan: ^1.7
README
这是基于 Laravel 框架的 suleymanozev/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
组件 来获取要调用的单数方法或进行翻译。
enum-helper
基础包摘要
您可以在他的 仓库 中看到 suleymanozev/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 suleymanozev/laravel-enum-helper
使用方法
您可以通过使用 LaravelEnumHelper
特性简单地使用此功能。
use Suleymanozev\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
,所以如果您只使用该属性,则可以使用2级数组。
// /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', ...
使用翻译字符串作为键
语言字符串存储在lang目录下的JSON文件中(例如 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()
result]。该方法的名称是属性的复数形式,所以如果你使用 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()
result],在 BackedEnum
上,[case name => property()
result] 否则。该方法的名称是属性的复数形式,所以如果你使用 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',...
特别感谢
- Datomatic 团队