PHP 8.1 is almost getting released, including support for Enumerations. I was testing some of the enum functionality and couldn't find much documentation about it. Hence my question: 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
)
containsValue()
function return \in_array($value, self::values(), true);
–
Oriole tryFrom
for that: php.net/manual/en/backedenum.tryfrom.php –
Rhyne array()
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. –
Weltpolitik 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 valuesAdds 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
Reflection
for all things classes, interfaces, enums.. –
Phobos Status::cases()
? –
Express 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
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";
}
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());
. –
Correa 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. Whoops –
Correa 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]
The 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"
]
© 2022 - 2024 — McMap. All rights reserved.
array_combine(self::names(), self::values())
. Having the names as array keys feels more natural to me. – Hilaire