[php] Enumerations on PHP

From PHP 8.1 onwards, you'll get native enumerations.

At its most basic level they'll work like this:

enum TransportMode {
  case Bicycle;
  case Car;
  case Ship;
  case Plane;
  case Feet;
}
function travelCost(Vehicle $vehicle, int $distance): int
{ /* implementation */ } 

$mode = TransportMode::Boat;

$bikeCost = travelCost(TransportMode::Bicycle, 90);
$boatCost = travelCost($mode, 90);

// this one would fail: (Enums are singletons, not scalars)
$failCost = travelCost('Car', 90);

Values

By default, enumerations are not backed by any kind of scalar. So TransportMode::Bicycle is not 0, and you cannot compare using > or < between enumerations.

But the following would work:

$foo = TransportMode::Car;
$bar = TransportMode::Car;

$foo === $bar; // true

$foo instanceof TransportMode; // true

$foo > $bar || $foo <  $bar; // false either way

Backed Enumerations

You can also have "backed" enums, where each enumeration case is "backed" by either an int or a string.

enum Metal: int {
  case Gold = 1932;
  case Silver = 1049;
  case Lead = 1134;
  case Uranium = 1905;
  case Copper = 894;
}
  • If one case has a backed value, all cases need to have a backed value, there are no auto-generated values.
  • Notice they type of the backed value is declard right after the enumeration name
  • Backed values are read only
  • Scalar values need to unique
  • Values need to be literals or literal expressions
  • To read the backed value you access the value property: Metal::Gold->value.

Finally, backed enumerations implement a BackedEnum interface internally, which exposes two methods:

  • from(int|string): self
  • tryFrom(int|string): ?self

They are almost equivalent, but the first one will throw an exception if the value is not found, and the seccond will simply return null.

Methods

Enumeratin may have methods, and thus implement interfaces.

interface TravelCapable
{
    public function travelCost(int $distance): int;
    public function requiresFuel(): bool;
}

enum TransportMode: int implements TravelCapable{
  case Bicycle = 10;
  case Car = 1000 ;
  case Ship = 800 ;
  case Plane = 2000;
  case Feet = 5;
  
  public function travelCost(int $distance): int
  {
    return $this->value * $distance;
  }
  
  public function requiresFuel(): bool {
    return match($this) {
        TransportMode::Car, TransportMode::Ship, TransportMode::Plane => true,
      TransportMode::Bicycle, TransportMode::Feet => false
    }
  }
}

Value listing

Both Pure Enums and Backed Enums internally implement the interface UnitEnum, which includes the (static) method UnitEnum::cases(), and allows to retrieve an array of the cases defined in the enumeration:

$modes = TransportMode::cases();

And now $modes is:

[
    TransportMode::Bicycle,
    TransportMode::Car,
    TransportMode::Ship,
    TransportMode::Plane
    TransportMode::Feet
]

Static methods

Enumerations can implement their own static methods, which would generally be used for specialized constructors.


This covers the basic. To get the whole thing, head on to the relevant RFC until the feature is released and published in PHPs documentation.