cerbero / enum
PHP 库,用于扩展枚举功能。
Requires
- php: ^8.1
Requires (Dev)
- pestphp/pest: ^1.21
- scrutinizer/ocular: ^1.9
- squizlabs/php_codesniffer: ^3.0
This package is auto-updated.
Last update: 2024-09-15 16:18:42 UTC
README
零依赖的 PHP 库,用于增强枚举功能。
📦 安装
Via Composer
composer require cerbero/enum
🔮 使用方法
要使用此包提供的所有功能来增强我们的枚举,我们可以在纯枚举和后端枚举中使用 Enumerates
特性
use Cerbero\Enum\Concerns\Enumerates; enum PureEnum { use Enumerates; case one; case two; case three; } enum BackedEnum: int { use Enumerates; case one = 1; case two = 2; case three = 3; }
分类
这些方法确定枚举是纯的还是后端的
PureEnum::isPure(); // true PureEnum::isBacked(); // false BackedEnum::isPure(); // false BackedEnum::isBacked(); // true
比较
我们可以检查枚举是否包含某些名称或值。纯枚举检查名称,而后端枚举检查值
PureEnum::has('one'); // true PureEnum::has('four'); // false PureEnum::doesntHave('one'); // false PureEnum::doesntHave('four'); // true BackedEnum::has(1); // true BackedEnum::has(4); // false BackedEnum::doesntHave(1); // false BackedEnum::doesntHave(4); // true
否则,我们可以让案例确定它们是否与名称或值匹配
PureEnum::one->is('one'); // true PureEnum::one->is(1); // false PureEnum::one->is('four'); // false PureEnum::one->isNot('one'); // false PureEnum::one->isNot(1); // true PureEnum::one->isNot('four'); // true BackedEnum::one->is(1); // true BackedEnum::one->is('1'); // false BackedEnum::one->is(4); // false BackedEnum::one->isNot(1); // false BackedEnum::one->isNot('1'); // true BackedEnum::one->isNot(4); // true
比较也可以在数组内进行
PureEnum::one->in(['one', 'four']); // true PureEnum::one->in([1, 4]); // false PureEnum::one->notIn('one', 'four'); // false PureEnum::one->notIn([1, 4]); // true BackedEnum::one->in([1, 4]); // true BackedEnum::one->in(['one', 'four']); // false BackedEnum::one->notIn([1, 4]); // false BackedEnum::one->notIn(['one', 'four']); // true
键解析
当我们提到“键”时,我们指的是在枚举中定义的任何元素,例如名称、值或案例实现的函数。以下是一个枚举的例子
enum BackedEnum: int { use Enumerates; case one = 1; case two = 2; case three = 3; public function color(): string { return match ($this) { static::one => 'red', static::two => 'green', static::three => 'blue', }; } public function isOdd(): bool { return match ($this) { static::one => true, static::two => false, static::three => true, }; } }
在此枚举中定义的键是 name
、value
(因为它是一个后端枚举)、color
和 isOdd
。我们可以通过调用 get()
来检索分配给案例的任何键
PureEnum::one->get('name'); // 'one' PureEnum::one->get('value'); // throws ValueError as it is a pure enum PureEnum::one->get('color'); // 'red' PureEnum::one->get(fn (PureEnum $caseOne) => $caseOne->isOdd()); // true BackedEnum::one->get('name'); // 'one' BackedEnum::one->get('value'); // 1 BackedEnum::one->get('color'); // 'red' BackedEnum::one->get(fn (BackedEnum $caseOne) => $caseOne->isOdd()); // true
乍一看,此方法可能显得有些过度,因为“键”可以直接像这样通过案例访问
BackedEnum::one->name; // 'one' BackedEnum::one->value; // 1 BackedEnum::one->color(); // 'red' BackedEnum::one->isOdd(); // true
然而,get()
对于动态解析键非常有用,因为键可能是一个属性、一个方法或一个闭包。它通常用于实现更高级的功能,我们很快就会探索这些功能。
初始化
枚举案例可以从其名称、值(如果后端)和 键 实例化
PureEnum::from('one'); // PureEnum::one PureEnum::from('four'); // throws ValueError PureEnum::tryFrom('one'); // PureEnum::one PureEnum::tryFrom('four'); // null PureEnum::fromName('one'); // PureEnum::one PureEnum::fromName('four'); // throws ValueError PureEnum::tryFromName('one'); // PureEnum::one PureEnum::tryFromName('four'); // null PureEnum::fromKey('name', 'one'); // CasesCollection<PureEnum::one> PureEnum::fromKey('value', 1); // throws ValueError PureEnum::fromKey('color', 'red'); // CasesCollection<PureEnum::one> PureEnum::fromKey(fn (PureEnum $case) => $case->isOdd(), true); // CasesCollection<PureEnum::one, PureEnum::three> PureEnum::tryFromKey('name', 'one'); // CasesCollection<PureEnum::one> PureEnum::tryFromKey('value', 1); // null PureEnum::tryFromKey('color', 'red'); // CasesCollection<PureEnum::one> PureEnum::tryFromKey(fn (PureEnum $case) => $case->isOdd(), true); // CasesCollection<PureEnum::one, PureEnum::three> BackedEnum::from(1); // BackedEnum::one BackedEnum::from('1'); // throws ValueError BackedEnum::tryFrom(1); // BackedEnum::one BackedEnum::tryFrom('1'); // null BackedEnum::fromName('one'); // BackedEnum::one BackedEnum::fromName('four'); // throws ValueError BackedEnum::tryFromName('one'); // BackedEnum::one BackedEnum::tryFromName('four'); // null BackedEnum::fromKey('name', 'one'); // CasesCollection<BackedEnum::one> BackedEnum::fromKey('value', 1); // CasesCollection<BackedEnum::one> BackedEnum::fromKey('color', 'red'); // CasesCollection<BackedEnum::one> BackedEnum::fromKey(fn (BackedEnum $case) => $case->isOdd(), true); // CasesCollection<BackedEnum::one, BackedEnum::three> BackedEnum::tryFromKey('name', 'one'); // CasesCollection<BackedEnum::one> BackedEnum::tryFromKey('value', 1); // CasesCollection<BackedEnum::one> BackedEnum::tryFromKey('color', 'red'); // CasesCollection<BackedEnum::one> BackedEnum::tryFromKey(fn (BackedEnum $case) => $case->isOdd(), true); // CasesCollection<BackedEnum::one, BackedEnum::three>
虽然纯枚举试图从名称中初始化案例,但后端枚举可以同时从名称和值中初始化。甚至键也可以用于初始化案例,然后案例被包装到 CasesCollection
中以允许进一步处理。
详细说明案例
可以对枚举的案例执行一系列操作。如果操作的最终结果是一个简单的案例列表,它们将包装到一个 CasesCollection
中以进行进一步处理,否则返回操作的最后结果。
PureEnum::collect(); // CasesCollection<PureEnum::one, PureEnum::two, PureEnum::three> PureEnum::count(); // 3 PureEnum::casesByName(); // ['one' => PureEnum::one, 'two' => PureEnum::two, 'three' => PureEnum::three] PureEnum::casesByValue(); // [] PureEnum::casesBy('color'); // ['red' => PureEnum::one, 'green' => PureEnum::two, 'blue' => PureEnum::three] PureEnum::groupBy('color'); // ['red' => [PureEnum::one], 'green' => [PureEnum::two], 'blue' => [PureEnum::three]] PureEnum::names(); // ['one', 'two', 'three'] PureEnum::values(); // [] PureEnum::pluck(); // ['one', 'two', 'three'] PureEnum::pluck('color'); // ['red', 'green', 'blue'] PureEnum::pluck(fn (PureEnum $case) => $case->isOdd()); // [true, false, true] PureEnum::pluck('color', 'shape'); // ['triangle' => 'red', 'square' => 'green', 'circle' => 'blue'] PureEnum::pluck(fn (PureEnum $case) => $case->isOdd(), fn (PureEnum $case) => $case->name); // ['one' => true, 'two' => false, 'three' => true] PureEnum::filter('isOdd'); // CasesCollection<PureEnum::one, PureEnum::three> PureEnum::filter(fn (PureEnum $case) => $case->isOdd()); // CasesCollection<PureEnum::one, PureEnum::three> PureEnum::only('two', 'three'); // CasesCollection<PureEnum::two, PureEnum::three> PureEnum::except('two', 'three'); // CasesCollection<PureEnum::one> PureEnum::onlyValues(2, 3); // CasesCollection<> PureEnum::exceptValues(2, 3); // CasesCollection<> PureEnum::sort(); // CasesCollection<PureEnum::one, PureEnum::three, PureEnum::two> PureEnum::sortDesc(); // CasesCollection<PureEnum::two, PureEnum::three, PureEnum::one> PureEnum::sortByValue(); // CasesCollection<> PureEnum::sortDescByValue(); // CasesCollection<> PureEnum::sortBy('color'); // CasesCollection<PureEnum::three, PureEnum::two, PureEnum::one> PureEnum::sortDescBy(fn (PureEnum $case) => $case->color()); // CasesCollection<PureEnum::one, PureEnum::two, PureEnum::three> BackedEnum::collect(); // CasesCollection<BackedEnum::one, BackedEnum::two, BackedEnum::three> BackedEnum::count(); // 3 BackedEnum::casesByName(); // ['one' => BackedEnum::one, 'two' => BackedEnum::two, 'three' => BackedEnum::three] BackedEnum::casesByValue(); // [1 => BackedEnum::one, 2 => BackedEnum::two, 3 => BackedEnum::three] BackedEnum::casesBy('color'); // ['red' => BackedEnum::one, 'green' => BackedEnum::two, 'blue' => BackedEnum::three] BackedEnum::groupBy('color'); // ['red' => [BackedEnum::one], 'green' => [BackedEnum::two], 'blue' => [BackedEnum::three]] BackedEnum::names(); // ['one', 'two', 'three'] BackedEnum::values(); // [1, 2, 3] BackedEnum::pluck(); // [1, 2, 3] BackedEnum::pluck('color'); // ['red', 'green', 'blue'] BackedEnum::pluck(fn (BackedEnum $case) => $case->isOdd()); // [true, false, true] BackedEnum::pluck('color', 'shape'); // ['triangle' => 'red', 'square' => 'green', 'circle' => 'blue'] BackedEnum::pluck(fn (BackedEnum $case) => $case->isOdd(), fn (BackedEnum $case) => $case->name); // ['one' => true, BackedEnum::filter('isOdd'); // CasesCollection<BackedEnum::one, BackedEnum::three> BackedEnum::filter(fn (BackedEnum $case) => $case->isOdd()); // CasesCollection<BackedEnum::one, BackedEnum::three> BackedEnum::only('two', 'three'); // CasesCollection<BackedEnum::two, BackedEnum::three> BackedEnum::except('two', 'three'); // CasesCollection<BackedEnum::one> BackedEnum::onlyValues(2, 3); // CasesCollection<> BackedEnum::exceptValues(2, 3); // CasesCollection<>'two' => false, 'three' => true] BackedEnum::sort(); // CasesCollection<BackedEnum::one, BackedEnum::three, BackedEnum::two> BackedEnum::sortDesc(); // CasesCollection<BackedEnum::two, BackedEnum::three, BackedEnum::one> BackedEnum::sortByValue(); // CasesCollection<BackedEnum::one, BackedEnum::two, BackedEnum::three> BackedEnum::sortDescByValue(); // CasesCollection<BackedEnum::three, BackedEnum::two, BackedEnum::one> BackedEnum::sortBy('color'); // CasesCollection<BackedEnum::three, BackedEnum::two, BackedEnum::one> BackedEnum::sortDescBy(fn (BackedEnum $case) => $case->color()); // CasesCollection<BackedEnum::one, BackedEnum::two, BackedEnum::three>
案例集合
当一个简单的案例列表由 案例操作 返回时,它被包装到一个 CasesCollection
中,该集合提供了一个流畅的 API 来执行对案例集的进一步操作。
PureEnum::filter('isOdd')->sortBy('color')->pluck('color', 'name'); // ['three' => 'blue', 'one' => 'red']
可以通过调用 collect()
或任何其他 案例操作 返回 CasesCollection
来收集案例
PureEnum::collect(); // CasesCollection<PureEnum::one, PureEnum::two, PureEnum::three> BackedEnum::only('one', 'two'); // CasesCollection<BackedEnum::one, BackedEnum::two>
我们可以在任何循环中迭代案例集合
foreach (PureEnum::collect() as $case) { echo $case->name; }
获取底层简单案例列表很容易
PureEnum::collect()->cases(); // [PureEnum::one, PureEnum::two, PureEnum::three]
有时我们可能需要提取集合中的第一个案例
PureEnum::filter(fn (PureEnum $case) => !$case->isOdd())->first(); // PureEnum::two
为了参考,以下是 CasesCollection
中所有可用的操作
PureEnum::collect()->cases(); // [PureEnum::one, PureEnum::two, PureEnum::three] PureEnum::collect()->count(); // 3 PureEnum::collect()->first(); // PureEnum::one PureEnum::collect()->keyByName(); // ['one' => PureEnum::one, 'two' => PureEnum::two, 'three' => PureEnum::three] PureEnum::collect()->keyByValue(); // [] PureEnum::collect()->keyBy('color'); // ['red' => PureEnum::one, 'green' => PureEnum::two, 'blue' => PureEnum::three] PureEnum::collect()->groupBy('color'); // ['red' => [PureEnum::one], 'green' => [PureEnum::two], 'blue' => [PureEnum::three]] PureEnum::collect()->names(); // ['one', 'two', 'three'] PureEnum::collect()->values(); // [] PureEnum::collect()->pluck(); // ['one', 'two', 'three'] PureEnum::collect()->pluck('color'); // ['red', 'green', 'blue'] PureEnum::collect()->pluck(fn (PureEnum $case) => $case->isOdd()); // [true, false, true] PureEnum::collect()->pluck('color', 'shape'); // ['triangle' => 'red', 'square' => 'green', 'circle' => 'blue'] PureEnum::collect()->pluck(fn (PureEnum $case) => $case->isOdd(), fn (PureEnum $case) => $case->name); // ['one' => true, 'two' => false, 'three' => true] PureEnum::collect()->filter('isOdd'); // CasesCollection<PureEnum::one, PureEnum::three> PureEnum::collect()->filter(fn (PureEnum $case) => $case->isOdd()); // CasesCollection<PureEnum::one, PureEnum::three> PureEnum::collect()->only('two', 'three'); // CasesCollection<PureEnum::two, PureEnum::three> PureEnum::collect()->except('two', 'three'); // CasesCollection<PureEnum::one> PureEnum::collect()->onlyValues(2, 3); // CasesCollection<> PureEnum::collect()->exceptValues(2, 3); // CasesCollection<> PureEnum::collect()->sort(); // CasesCollection<PureEnum::one, PureEnum::three, PureEnum::two> PureEnum::collect()->sortDesc(); // CasesCollection<PureEnum::two, PureEnum::three, PureEnum::one> PureEnum::collect()->sortByValue(); // CasesCollection<> PureEnum::collect()->sortDescByValue(); // CasesCollection<> PureEnum::collect()->sortBy('color'); // CasesCollection<PureEnum::three, PureEnum::two, PureEnum::one> PureEnum::collect()->sortDescBy(fn (PureEnum $case) => $case->color()); // CasesCollection<PureEnum::one, PureEnum::two, PureEnum::three> BackedEnum::collect()->cases(); // [BackedEnum::one, BackedEnum::two, BackedEnum::three] BackedEnum::collect()->count(); // 3 BackedEnum::collect()->first(); // BackedEnum::one BackedEnum::collect()->keyByName(); // ['one' => BackedEnum::one, 'two' => BackedEnum::two, 'three' => BackedEnum::three] BackedEnum::collect()->keyByValue(); // [1 => BackedEnum::one, 2 => BackedEnum::two, 3 => BackedEnum::three] BackedEnum::collect()->keyBy('color'); // ['red' => BackedEnum::one, 'green' => BackedEnum::two, 'blue' => BackedEnum::three] BackedEnum::collect()->groupBy('color'); // ['red' => [BackedEnum::one], 'green' => [BackedEnum::two], 'blue' => [BackedEnum::three]] BackedEnum::collect()->names(); // ['one', 'two', 'three'] BackedEnum::collect()->values(); // [1, 2, 3] BackedEnum::collect()->pluck(); // [1, 2, 3] BackedEnum::collect()->pluck('color'); // ['red', 'green', 'blue'] BackedEnum::collect()->pluck(fn (BackedEnum $case) => $case->isOdd()); // [true, false, true] BackedEnum::collect()->pluck('color', 'shape'); // ['triangle' => 'red', 'square' => 'green', 'circle' => 'blue'] BackedEnum::collect()->pluck(fn (BackedEnum $case) => $case->isOdd(), fn (BackedEnum $case) => $case->name); // ['one' => true, 'two' => false, 'three' => true] BackedEnum::collect()->filter('isOdd'); // CasesCollection<BackedEnum::one, BackedEnum::three> BackedEnum::collect()->filter(fn (BackedEnum $case) => $case->isOdd()); // CasesCollection<BackedEnum::one, BackedEnum::three> BackedEnum::collect()->only('two', 'three'); // CasesCollection<BackedEnum::two, BackedEnum::three> BackedEnum::collect()->except('two', 'three'); // CasesCollection<BackedEnum::one> BackedEnum::collect()->onlyValues(2, 3); // CasesCollection<BackedEnum::two, BackedEnum::three> BackedEnum::collect()->exceptValues(2, 3); // CasesCollection<BackedEnum::one> BackedEnum::collect()->sort(); // CasesCollection<BackedEnum::one, BackedEnum::three, BackedEnum::two> BackedEnum::collect()->sortDesc(); // CasesCollection<BackedEnum::two, BackedEnum::three, BackedEnum::one> BackedEnum::collect()->sortByValue(); // CasesCollection<BackedEnum::one, BackedEnum::two, BackedEnum::three> BackedEnum::collect()->sortDescByValue(); // CasesCollection<BackedEnum::three, BackedEnum::two, BackedEnum::one> BackedEnum::collect()->sortBy('color'); // CasesCollection<BackedEnum::three, BackedEnum::two, BackedEnum::one> BackedEnum::collect()->sortDescBy(fn (BackedEnum $case) => $case->color()); // CasesCollection<BackedEnum::one, BackedEnum::two, BackedEnum::three>
📆 更新日志
请参阅 CHANGELOG 以获取有关最近更改的更多信息。
🧪 测试
composer test
💖 贡献
请参阅CONTRIBUTING和CODE_OF_CONDUCT以获取详细信息。
🧯 安全性
如果您发现任何与安全性相关的问题,请通过电子邮件andrea.marco.sartori@gmail.com联系,而不是使用问题跟踪器。
🏅 致谢
⚖️ 许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。