PHP: My approach to saving Enum data values
Let me make a custom class to save them.
After reading Salar’s way to “save” enum values, I decided to make my own way to save Enum values through a class called Enumerate
.
The main task of an Enumerate
instance is to allow to be set a valid state from a given list. If the state is not in the list, an Exception should be thrown because not doing so could break the application.
The idea is to let the class to hold a given number of possible “states”, and set one of these states using a dynamic call.
$enum = Enumerate::from([
'received', 'prepared', 'delivering', 'delivered'
]);$enum->preparing();echo $enum; // "preparing"
That’s it. For safety, if you set an invalid state, you will get a BadMethodCallException
.
Let’s check the class itself:
What about keys and values?
You can also create a state map, which is useful when you have simple states, but complex underlying values like class names, object instances or callables.
$enum = Enumerate::from([
'received' => Received::class,
'prepared' => Prepared::class,
'delivering' => Delivered::class,
'delivered' => fn($something) => App::make($something),
]);
When you set a set a state name, you will be also able to get the real value of the state instead of just the name with the value()
method, among over handy helpers.
$enum->delivered();echo $enum->is('delivered'); // "true"
echo $enum->is('prepared'); // "false"echo $enum->has('prepared'); // "true"
echo $enum->has('in-transit'); // "false"echo $enum->current(); // "received"
echo $enum->value(); // "App\States\Received"
You can start an Enumerate
instance initialized from the get go:
$enum = Enumerate::from(['foo', 'bar'], 'foo');
The good part of this class is you can extend it and add an initial value so it can be instanced with a default state already set.
class PackageStates extends Enumerate
{
protected $current = 'received';
protected $states = [
'received', 'prepared', 'delivering', 'delivered'
];
}
That’s it. No more need to hack your way into classes, use constants where you shouldn’t, or create obnoxious functions. Just imagine this:
public function notify(Package $package)
{
if ($package->is('delivered')) {
return 'Your package has been delivered already';
} return 'Your package is on-transit to the destination';
}
This helper is included in my Laratraits package. If you want convenient helpers for your project, give it a go.