MulchProductions

ENUMS in PHP

Mittlerweile wohl bekannt: PHP unterstützt von Haus aus keine Enumerations und bietet daher auch nicht den Datentyp ENUM. Gerade wenn man aus der Java Welt kommt und den Einsatz von Enums gewohnt ist, möchte man ungern darauf verzichten.
Daher hat sich das Kajona Team mit der Problematik beschäftigt und einen - wie wir finden - recht brauchbaren Workaround entwickelt.
Dabei dreht sich alles um eine zentrale, abstrakte Klasse: Enum (bzw. in der aktuellen Kajona Coding-Convention: class_enum).
Die aktuellste Variante der Klasse inklusive der PHPDocs befindet sich auf GitHub: https://github.com/kajona/kajonacms/blob/master/module_system/system/class_enum.php
abstract class class_enum {

protected abstract function getArrValues();

private $strValue = null;

private function __construct($strCurValue) {
$this->strValue = $strCurValue;
}

public static function __callStatic($strName, $arrArguments) {
$objEnum = new static($strName);
if(!in_array($strName, $objEnum->getArrValues())) {
throw new class_exception($strName ." is not allowed for enum ".get_called_class(), class_exception::$level_FATALERROR);
}

return $objEnum;
}

public function equals(class_enum $objB) {
return $this->strValue == $objB->strValue && get_class($this) == get_class($objB);
}

public function __toString() {
return $this->strValue."";
}
}

Interessant wird das Zusammenspiel dann erst, wenn die Basisklasse in einer konkreten Klasse abgeleitet wird:
 
/**
* Class class_test_enum
* @method static class_test_enum a()
* @method static class_test_enum b()
* @method static class_test_enum c()
*/
class class_test_enum extends class_enum {
protected function getArrValues() {
return array("a", "b", "c");
}
}

In diesem Fall wird deklariert, dass es für den ENUM "class_test_enum" drei gültige Ausprägungen gibt: a, b und c. Durch die PHPDoc Kommentare kann innnerhalb moderner IDEs darauf nun komplett zugegriffen werden:



Ebenso kann damit nun recht einfach gearbeitet werden:
public function testEnums() {

$objEnum = class_test_enum::a();
$this->assertNotNull($objEnum);
$this->assertEquals($objEnum."", "a");

$this->assertTrue($objEnum->equals(class_test_enum::a()));
$this->assertTrue(!$objEnum->equals(class_test_enum::b()));

$objEnum = class_test_enum::d();
$this->assertNull($objEnum);

}

Die ENUM Variante stellt also eine Möglichkeit dar, einerseits typisierte Parameter an Funktionen übergeben zu können (Type Hinting), andereseits darüber hinaus auch die Gültigkeit des Wertes des Parameters eindeutig zu validieren.