I use this rule of thumb:
- If it is an "enumerable" set of data (finite set, you can list them all, not likely to change, it can change, but not likely), AND it interferes in the application logic/workflow (such as your draft/published/... state), then I would choose an Enum
- Otherwise, either lookup table, config file, external JSON file, etc. that is easier to change/build on the-fly
You can easily use a fancy string for an Enum value. PHP Enums accept traits, I have this trait (suppressed some other methods for brevity)
<?php
namespace App\Enums;
trait EnumUtils
{
public function __invoke(): int|string
{
return $this->value;
}
// Allows to call Enum::VALUE() , instead of Enum::VALUE->value
public static function __callStatic($name, $arguments)
{
/** @var static $case */
foreach (static::cases() as $case) {
if ($case->name === $name) {
return $case->value;
}
}
return new \RuntimeException('Invalid case ' . $name . ' for enum ' . static::class);
}
// easy comparision $enum->is(Enum::VALUE_A, Enum::VALUE_B)
public function is(self ...$others): bool
{
return in_array($this, $others, true);
}
public function isNot(self ...$others): bool
{
return ! $this->is(...$others);
}
public static function getRandomValue(): int|string
{
$cases = static::cases();
return $cases[\array_rand($cases)]->value;
}
public function label(): string
{
if (! $this instanceof LocalizedEnum) {
return \strval($this->name);
}
$key = 'enums.' . $this::class . '.' . $this->value;
if (\trans()->has($key)) {
return \trans($key);
}
return \strval($this->name);
}
/**
* Get the enum as an array formatted for a select.
*
* @return array<int|string, string>
*/
public static function toSelectArray(): array
{
$cases = static::cases();
$selectArray = [];
/** @var self $case */
foreach ($cases as $case) {
$selectArray[$case->value] = $case->label();
}
return $selectArray;
}
}
See the label() method. LocalizedEnum is just an empty interface I add to the Enums I want to give translation labels (Enums can also implement interfaces)
So in my ./lang/en/enums.php file I have something like this:
<?php
use App\Enums\Role;
use App\Enums\Timespan;
return [
Timespan::class => [
Timespan::DAYS() => 'Days',
Timespan::HOURS() => 'Hours',
],
Role::class => [
Role::SYSTEM() => 'System Admin',
Role::ADMIN() => 'Administrator',
Role::STAFF() => 'Staff',
Role::REPORTING() => 'Reporting user',
Role::USER() => 'Regular user',
],
// ... other enums
];
Than you can call Enum::VALUE->label() for pretty labels, and as a bonus, easy translation (if needed).