Generic enum type in php

Viewed 29

How can I specify an argument type to take any enum value?

Something like function processEnum(enum $value) would be ideal, however nothing seems to exist?

enum Numbers: int {
  case FIRST = 1;
  case SECOND = 2;
}


enum Foo: string {
  case BAR = 'bar';
}

function printEnum($enumValue) {
  echo $enumValue->value;
}

printEnum(Numbers::FIRST); // 1
printEnum(Foo::BAR); // 'bar'
printEnum('fail'); // I want to reject this!

Additionally it would be nice to separate backed vs non-backed enums or additionally backed types; enums that are backed as strings for example.

2 Answers

All enums implement the UnitEnum interface, and backed enums (those with a type and a ->value property) also implement the BackedEnum interface. You can write type constraints for those:

enum Numbers: int {
  case FIRST = 1;
  case SECOND = 2;
}
enum Foo: string {
  case BAR = 'bar';
}
enum Something {
   case WHATEVER;
}

function doSomething(UnitEnum $enumValue) {
  echo "blah\n";
}
function printEnum(BackedEnum $enumValue) {
  echo $enumValue->value, "\n";
}

doSomething(Numbers::FIRST); // blah
doSomething(Foo::BAR); // blah
doSomething(Something::WHATEVER); // blah
doSomething('fail'); // TypeError

printEnum(Numbers::FIRST); // 1
printEnum(Foo::BAR); // 'bar'
printEnum(Something::WHATEVER); // TypeError
printEnum('fail'); // TypeError

Version one with interfaces

<?php
interface MyEnums {} 

enum Numbers : int implements MyEnums {
  case FIRST = 1;
  case SECOND = 2;
}


enum Foo : string implements MyEnums{
  case BAR = 'bar';
}

function printEnum(MyEnums $enumValue) {
  echo $enumValue->value;
}

printEnum(Numbers::FIRST); // 1
printEnum(Foo::BAR); // 'bar'
printEnum('fail'); // Fatal error: Uncaught TypeError: printEnum(): Argument #1 ($enumValue) must be of type MyEnums

Version two with exception, but will also take any class with public property 'value'

<?php

enum Numbers : int {
  case FIRST = 1;
  case SECOND = 2;
}


enum Foo : string {
  case BAR = 'bar';
}

function printEnum($enumValue) {
  echo $enumValue->value ?? throw new Exception('Rejected');
}

printEnum(Numbers::FIRST); // 1
printEnum(Foo::BAR); // 'bar'
printEnum('fail'); // throws an exception

Related