PHP 8.1 adds support for Enumerations. I was testing some of the enum functionality and couldn't find much documentation about it.
How do I get all values of an enum?
For basic enums:
$suits = array_column(Suit::cases(), 'name');
For backed enums where you want the values:
$suits = array_column(Suit::cases(), 'value');
You could then do something like this:
trait EnumToArray
{
public static function names(): array
{
return array_column(self::cases(), 'name');
}
public static function values(): array
{
return array_column(self::cases(), 'value');
}
public static function array(): array
{
return array_combine(self::values(), self::names());
}
}
enum Suit: string
{
use EnumToArray;
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
Suit::array() will return:
Array
(
[H] => Hearts
[D] => Diamonds
[C] => Clubs
[S] => Spades
)
array_combine(self::names(), self::values()). Having the names as array keys feels more natural to me.containsValue() function return \in_array($value, self::values(), true);tryFrom for that: php.net/manual/en/backedenum.tryfrom.phparray() method can also be written with array_column and the 3rd param for index_key column, like this: array_column(self::cases(), 'value', 'name') and will result in an assoc array with names as keys.After some research I found the answer. You can use the static method: cases().
enum Status
{
case PAID;
case Cancelled;
}
Status::cases();
The cases method will return an array with an enum (UnitEnum interface) for each value.
Need the values and not Enum instances?
I've written a Composer package for this, othyn/php-enum-enhancements, as the UnitEnum::cases() method wasn't what I was looking for, as that returns an array of MySuperCoolEnum instances instead of the underlying values as their raw type, which is what I wanted.
Its a trait that can be easily added to any enum that does the following:
Adds a new static UnitEnum::valueArray(): array method that returns all values within an Enum as an equally typed array of Enum values
Adds a new static UnitEnum::valueList(string $separator = ', '): string method that returns all values within an Enum as a comma separated list string
In which produces the following for normal Enum's:
<?php
namespace App\Enums;
use Othyn\PhpEnumEnhancements\Traits\EnumEnhancements;
enum TestEnum
{
use EnumEnhancements;
case Alpha;
case Bravo;
case Charlie;
case Delta;
case Echo;
}
var_dump(TestEnum::valueArray());
// Results in the following being printed:
// array(5) {
// [0]=>
// string(5) "Alpha"
// [1]=>
// string(5) "Bravo"
// [2]=>
// string(7) "Charlie"
// [3]=>
// string(5) "Delta"
// [4]=>
// string(4) "Echo"
// }
var_dump(TestEnum::valueList());
// Results in the following being printed:
// string(34) "Alpha, Bravo, Charlie, Delta, Echo"
var_dump(TestEnum::valueList(separator: ':'));
// Results in the following being printed:
// string(30) "Alpha:Bravo:Charlie:Delta:Echo"
... and the following for Backed Enum's, the following being a string example:
<?php
namespace App\Enums;
use Othyn\PhpEnumEnhancements\Traits\EnumEnhancements;
enum TestStringBackedEnum: string
{
use EnumEnhancements;
case Alpha = 'alpha';
case Bravo = 'bravo';
case Charlie = 'charlie';
case Delta = 'delta';
case Echo = 'echo';
}
var_dump(TestStringBackedEnum::valueArray());
// Results in the following being printed:
// array(5) {
// [0]=>
// string(5) "alpha"
// [1]=>
// string(5) "bravo"
// [2]=>
// string(7) "charlie"
// [3]=>
// string(5) "delta"
// [4]=>
// string(4) "echo"
// }
var_dump(TestStringBackedEnum::valueList());
// Results in the following being printed:
// string(34) "alpha, bravo, charlie, delta, echo"
var_dump(TestStringBackedEnum::valueList(separator: ':'));
// Results in the following being printed:
// string(30) "alpha:bravo:charlie:delta:echo"
... and yes it works on int's too!
There are more examples in the Usage part of the package's README.
In addition to UnitEnum::cases() you can use ReflectionEnum with this
$reflection = new ReflectionEnum(Status::class);
$reflection->getCases();
note that in both cases you will not be able to get the enum methods. but as long as the ReflectionEnum is extending the ReflectionClass so you can use the rest of ReflectionClass methods such as getMethods
I have used the following in my project;
public static function toAssociativeArray(): array
{
foreach(self::cases() as $case) {
$array[$case->value] = $case->name;
}
return $array;
}
Which results in an associative array like this;
using strings as values
enum DiaryRole: string
{
case DANGER = 'red';
case WARNING = 'yellow';
case SAFE = 'green';
}
$array = [
'red' => 'DANGER',
'yellow' => 'WARNING',
'green' => 'SAFE'
];
or when using integers as values
enum DiaryRole: int
{
case DANGER = 1;
case WARNING = 2;
case SAFE = 3;
}
$array = [
1 => 'DANGER',
2 => 'WARNING',
3 => 'SAFE'
];
You can now use the array to get any information you need, and you can get only the columns or values using array_keys() or array_values()
I have used this code to easily foreach through them in a form select
Another way to get just the values of the enum is by following this approach:
<?php namespace JCKCon\Enums;
enum UsersPermissions: string
{
case CREATE = "create";
case UPDATE = "update";
case DELETE = "delete";
case VIEW = "view";
case PUBLISH = "publish";
public static function toArray()
{
$values = [];
foreach (self::cases() as $props) {
array_push($values, $props->value);
}
return $values;
}
}
dd(UsersPermissions::toArray());
/**
array:5 [
0 => "create"
1 => "update"
2 => "delete"
3 => "view"
4 => "publish"
]
**/
value is not a defined property in this case. You should use $props->name. Also, I would rewrite the the toArray method to this: return array_map(fn($case) => $case->name, self::cases());.value is not a defined property in this case. You should use $props->name. I didn't pay attention to it to see it's a backed enum. WhoopsThe simplest one-liner:
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
array_column(Suit::cases(), 'name', 'value');
It would return:
[
"H" => "Hearts",
"D" => "Diamonds",
"C" => "Clubs",
"S" => "Spades"
]
If you need to swap keys and values:
array_column(Suit::cases(), 'value', 'name');
[
"Hearts" => "H",
"Diamonds" => "D",
"Clubs" => "C",
"Spades" => "S"
]
I think the best options is using a trait for that.
For example: EnumsToArray.php
<?php
namespace App\Traits;
trait EnumsToArray {
public static function toArray(): array {
return array_map(
fn(self $enum) => $enum->value,
self::cases()
);
}
}
And later, in you enum you should have:
use App\Traits\EnumsToArray;
Enum Currency: string {
use EnumsToArray;
case DOLLAR = "usd";
case EURO = "eur";
}
I wrapped a slitly changed approach from @Michael up in a small package, cause I needed it in multiple projects:
https://github.com/laracraft-tech/laravel-useful-traits#usefulenums
Install via composer:
composer require laracraft-tech/laravel-useful-traits
This is how it is working:
use LaracraftTech\LaravelUsefulTraits\UsefulEnums;
enum PaymentType: int
{
use UsefulEnums;
case Pending = 1;
case Failed = 2;
case Success = 3;
}
PaymentType::names(); // return ['Pending', 'Failed', 'Success']
PaymentType::values(); // return [1, 2, 3]
PaymentType::array(); // return ['Pending' => 1, 'Failed' => 2, 'Success' => 3]
protected function casts(): array { return [ 'paymentType' => PaymentType::class, ]; }