A tiny helper library that enriches PHP 8.1+ native enum
with labels, tags, and a handful of utility methods.
- PHP ≥ 8.1 ‑ native
enumrequired - No external dependencies – pure PHP
composer require astandkaya/ex-enumuse ExEnum\Attributes\Extension;
use ExEnum\Traits\HasExtension;
enum Suit: string
{
/* 1. Add the trait */
use HasExtension;
/* 2. Decorate each case with #[Extension(...)] */
#[Extension(
label: 'ハート', // optional, default is case name
tags: ['red'], // optional, default is `[]`
order: 1, // optional, default is `0`
)]
case Hearts = 'hearts';
#[Extension(
label: 'ダイア',
tags: ['red', 'not_hearts'],
order: 2,
)]
case Diamonds = 'diamonds';
#[Extension(
label: 'クラブ',
tags: ['black', 'not_hearts'],
order: 3,
)]
case Clubs = 'clubs';
#[Extension(
label: 'スペード',
tags: ['black', 'not_hearts'],
order: -1,
)]
case Spades = 'spades';
}Every Suit case now carries an arbitrary label (string) and tags (string[]),
plus your enum automatically gains dozens of helper methods 👇
Suit::fromName('Hearts');
// enum(Suit::Hearts)
Suit::tryFromName('Spades');
// enum(Suit::Hearts) or nullSuit::names();
// array(4) {
// [0]=>
// string(6) "Hearts"
// [1]=>
// string(8) "Diamonds"
// [2]=>
// string(5) "Clubs"
// [3]=>
// string(6) "Spades"
// }
Suit::values();
// array(4) {
// [0]=>
// string(6) "hearts"
// [1]=>
// string(8) "diamonds"
// [2]=>
// string(5) "clubs"
// [3]=>
// string(6) "spades"
// }
Suit::labels();
// array(4) {
// [0]=>
// string(9) "ハート"
// [1]=>
// string(9) "ダイア"
// [2]=>
// string(9) "クラブ"
// [3]=>
// string(12) "スペード"
// }Suit::casesOnly(['not_hearts']);
// array(3) {
// [0]=>
// enum(Suit::Diamonds)
// [1]=>
// enum(Suit::Clubs)
// [2]=>
// enum(Suit::Spades)
// }
Suit::casesExcept(['red']);
// array(2) {
// [0]=>
// enum(Suit::Clubs)
// [1]=>
// enum(Suit::Spades)
// }$card = Suit::Hearts;
$card->hasTag('red');
// bool(true)
$card->hasTag('not_hearts');
// bool(false)
$card->hasTags(['red', 'not_hearts']);
// bool(true)
$card->hasTags(['red', 'unknown']);
// bool(false)Suit::sortBy();
// array(4) {
// [0]=>
// enum(Suit::Spades)
// [1]=>
// enum(Suit::Hearts)
// [2]=>
// enum(Suit::Diamonds)
// [3]=>
// enum(Suit::Clubs)
// }
Suit::sortByAsc();
// array(4) {
// [0]=>
// enum(Suit::Spades)
// [1]=>
// enum(Suit::Hearts)
// [2]=>
// enum(Suit::Diamonds)
// [3]=>
// enum(Suit::Clubs)
// }
Suit::sortByDesc();
// array(4) {
// [0]=>
// enum(Suit::Clubs)
// [1]=>
// enum(Suit::Diamonds)
// [2]=>
// enum(Suit::Hearts)
// [3]=>
// enum(Suit::Spades)
// }$card = Suit::Hearts;
$card->label();
// string(9) "ハート"
$card->isHearts();
// bool(true)
$card->isDiamonds();
// bool(false)By default, methods like casesOnly() / casesExcept() / sortBy() / map() / filter() return plain PHP arrays.
castArrayWith() registers a closure that wraps the output — useful for converting to a Collection in Laravel.
// Laravel: In AppServiceProvider::boot()
Suit::castArrayWith(fn(array $cases) => collect($cases));
// All array-returning methods now return a Collection
Suit::casesOnly(['red']); // → Collection
Suit::casesExcept(['red']); // → Collection
Suit::sortBy(); // → Collection
Suit::map(fn($c) => $c->label()); // → Collection
Suit::filter(fn($c) => $c->hasTag('red')); // → CollectionNote:
reduce()is not affected as it does not return an array.
label() can be overridden at runtime via a closure — useful for per-screen display names or when you prefer not to define labels in the #[Extension] attribute.
// In AppServiceProvider::boot() or a Controller — inject a resolver for all cases at once
Suit::injectLabels(function (Suit $case): string {
return match ($case) {
Suit::Hearts => 'Cœur',
Suit::Diamonds => 'Carreau',
default => $case->label(), // falls back to the original label without recursion
};
});
$card = Suit::Hearts;
$card->label(); // string(5) "Cœur"
// Reset when no longer needed
Suit::resetLabels();
$card->label(); // string(9) "ハート"Note: The resolver persists for the lifetime of the PHP process. Call
resetLabels()explicitly when the override should only apply to a limited scope.
Suit::map(fn(Suit $suit) => $suit->label());
// array(4) {
// [0]=>
// string(9) "ハート"
// [1]=>
// string(9) "ダイア"
// [2]=>
// string(9) "クラブ"
// [3]=>
// string(12) "スペード"
// }
Suit::reduce(fn(string $carry, Suit $suit) => $carry . $suit->label(), '');
// string(39) "ハートダイアクラブスペード"
Suit::filter(fn(Suit $suit) => $suit->hasTag('red'));
// array(2) {
// [0]=>
// enum(Suit::Hearts)
// [1]=>
// enum(Suit::Diamonds)
// }| Method | Returns | Description |
|---|---|---|
Suit::random() |
static |
Pick a random case |
Suit::toArray() |
array [name => value, …] |
Enum to associative array |
Suit::jsonSerialize() |
same as toArray() |
JSON-ready representation |