Skip to content

Instantly share code, notes, and snippets.

@AndrewGreen
Last active August 29, 2015 13:57
Show Gist options
  • Save AndrewGreen/9846282 to your computer and use it in GitHub Desktop.
Save AndrewGreen/9846282 to your computer and use it in GitHub Desktop.
Idea for PHP typesafe enum
<?php
/**
* To create some typesafe enums, just extend this class, declare some static
* properties, then call YourClassName::setUp(). Example follows.
*
* Disadvantages:
* - Since the enums are public properties, they could be modified by
* mistake (or intentionally by malicious code).
* - YourClassName::setUp() must be called.
* - $ required in front of enum name.
*
* Advantages:
* - IDE autocompletion should work.
*/
abstract class TypesafeEnum {
private $name;
public static function setUp() {
$calledClassName = get_called_class();
$calledClass = new ReflectionClass( $calledClassName );
$props = $calledClass->getProperties( ReflectionProperty::IS_STATIC );
foreach ( $props as $prop ) {
$prop->setValue( new $calledClassName( $prop->getName() ) );
}
}
private function __construct( $name ) {
$this->name = $name;
}
public function __toString() {
return $this->name;
}
}
// Example use
final class MyHappyEnum extends TypesafeEnum {
// Don't initialize these, just declare them.
static $ENUM_ONE;
static $ENUM_TWO;
static $ENUM_THREE;
}
// Gotta call this somewhere, but only once. Could put it in the same file as
// the concrete class, I think.
MyHappyEnum::setUp();
// Here's the function we'll use to demonstrate
$func = function( MyHappyEnum $enum ) {
// Got the right class
print 'Class of parameter is ' . get_class( $enum ) . "\n";
// __toString() works
print 'Name is ' . $enum . "\n";
// Switch also works normally
switch ( $enum ) {
case MyHappyEnum::$ENUM_ONE:
print "Switch: one\n";
break;
case MyHappyEnum::$ENUM_TWO:
print "Switch: two\n";
break;
case MyHappyEnum::$ENUM_THREE:
print "Switch: three\n";
break;
default:
throw new Exception( "Shouldn't happen." );
}
};
print ( "Testing call with " . MyHappyEnum::$ENUM_TWO . "\n\n" );
$func( MyHappyEnum::$ENUM_TWO );
print ( "\n\nTesting call with " . MyHappyEnum::$ENUM_THREE . "\n\n" );
$func( MyHappyEnum::$ENUM_THREE );
// All of these cause a fatal error. Uncomment any one to try it.
// $func( new MyHappyEnum( 'Can\'t instantiate anywhere else.' ) );
// $func( 'Type hint prevents passing anything else.' );
// $func( MyHappyEnum::$CAN_T_USE_NON_EXISTENT_ENUM );
@AndrewGreen
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment