I basically want an enum-like class in PHP. My enum should have a few values (they are all static). Let's say I want to have an enum that has an ID (the ID must never, ever change), and a name (the name must not change during runtime, it can change during compile-time -- e.g. from changes made to the code). The state must not have any side-effects (i.e. they are only getters and instance variables cannot be changed). A state must also not be created during runtime except when initializing the class.
For my concert example, I have three possible states: OPEN, CLOSED, and UNKOWN:
class MyState {
const STATE_OPEN = new MyState(1, "open");
const STATE_CLOSE = new MyState(2, "closed");
const STATE_UNKOWN = new MyState(3, "unkown");
private $name;
private $state;
private function __construct(int $state, string $name) {
$this->state = $state;
$this->name = $name;
}
public function getName() : string {
return $this->name;
}
public function getState() : int {
return $this->state;
}
public function getStateByID(int $state) : MyState { ... }
public function getStateByName(string $name) : MyState { ... }
}
I want to refer to each state unambiguously in my code (MyState::STATE_OPEN, etc). This should also ensure that a compiler/linter/etc can verify that the state actually exists (there is no guarantee that getStateByID
does not throw an exception).
There are also some (de)serializers that can load a state after it has been saved (by using the never changing ID).
Unfortunately, I cannot set const or static instance variables if their object is from the same class. I get the following error:
Constant expression contains invalid operations
How can this be best accomplished in PHP? I know I can easily create an enum with just an int (class MyState { const STATE_OPEN = 1; }
) but that has a major disadvantage: the enum is not an object and thus cannot have methods. I cannot use type hinting this way and I might pass an invalid enum. E.g., function takeMyState(int $state)
can actually use an enum that has never been defined.