PHP 8.1 introduced Enums, providing a structured way to define a fixed set of values. However, there are times when we need additional functionality, such as dynamically retrieving enum values, making enum cases callable, or getting structured attributes. This is where a trait can be useful.
The Problem with Basic Enums
Consider this basic OrderStatus enum:
enum OrderStatus: string{ case PENDING = 'pending'; case COMPLETED = 'completed'; case CANCELED = 'canceled';}
To access a case value, we typically write:
echo OrderStatus::PENDING->value; // Outputs: 'pending'
But what if we want to:
- ✅ Call an enum case like a function?
- ✅ Get an enum case value dynamically using a static method?
- ✅ Retrieve both name and value easily?
This is where a trait comes in handy.
Create InvokableCases Trait
Let’s define a InvokableCases trait that adds these features:
namespace App\Constants\Traits;
trait InvokableCases{ public function __invoke() { return $this->value; }
public static function __callStatic(mixed $name, mixed $arguments): mixed { return collect(self::cases())->firstWhere('name', $name)->value; }
public function attributes(): array { return [ 'name' => $this->name, 'value' => $this->value, ]; }}
What This Trait Does?
__invoke()
Makes an enum case callable, returning its value when invoked.__callStatic()
Allows retrieving an enum value dynamically using a static method call.attributes()
Returns an array with the enum’s name and value.
Using the Trait in an Enum
Now, let’s apply this trait to our OrderStatus enum:
enum OrderStatus: string{ use InvokableCases;
case PENDING = 'pending'; case COMPLETED = 'completed'; case CANCELED = 'canceled';}
Practical Usage Examples
Calling an Enum Case Like a Function
$status = OrderStatus::PENDING;echo $status(); // Outputs: 'pending'
Getting Enum Values Dynamically
echo OrderStatus::PENDING(); // Outputs: 'pending'echo OrderStatus::COMPLETED(); // Outputs: 'completed'
Retrieving Enum Attributes
print_r(OrderStatus::CANCELED->attributes());
Output:
[ 'name' => 'CANCELED', 'value' => 'canceled']
Conclusion
By using the InvokableCases trait, we have enhanced PHP Enums to be callable, dynamically accessible, and provide structured attributes. This makes Enums much more flexible and easier to use in real-world applications. 🚀