===== [PHP] Enum ===== Enums sind leider in PHP nicht wirklich implementiert. Mit dieser Abstrakten Klasse ist es relativ einfach um Enums zu erstellen und zu verwenden =====Beispiele===== ====Einfache Anwendung==== Als erstes defineren wir einfach mal ein Enum mit jeweils einem Wert. equal(Size::XL())) ? 'Du bist dick
': 'na schön
'; //und den Enum gegen die Variable echo (Size::XL()->equal($m)) ? 'Du bist dick
': 'na schön
'; ?>
Ausgabe: Du bist dick na schön ====Weitere Varianten einen einfachen Enum zu erstellen==== //Ein Einfacher Enum über einen Array erstellen. Array(name=>Value) createEnum('Sex', array('men' => 'm', 'women' => 'w')); echo Sex::men()->value; //m //Einfache Enums, bei denen die Namen und Values identisch sind, können noch einfacher erstellt werden createEnum('Lang', 'de', 'en'); echo Lang::de()->value; //de Enum::create('Color', 'red', 'blue', 'green'); echo Color::red()->value; //red ====Verschiedene Zugriffe==== //Ausgabe des Wertes echo $m->value; //Ein Enum anhand des Wertes ermitteln $s = Size::getEnum('S'); //Ein Enum anhand des Keys ermitteln $l = Size::getEnumKey('L'); ====Der Enum als Funktionsparameter==== //Ein Wert aussuchen $m = Size::M(); //Einer Funktion den Enum als Parameter mitgeben function checkStock(Size $isize){ //TODO: Bestand mittels DB abfragen. Hier als Beispiel ist es Hardcodiert switch ($isize){ case Size::S(): return 3; case Size::M(): return 10; case Size::L(): return 0; } } //Funktion aufrufen echo checkStock($m); //10 ====Enum mit mehreren Paramtern==== //Ein Enum mit weiteren Parametern class Size extends Enum{ //Zuerst die Parameter defineren. In dem Fall die Grössenbez. für Europa un Amerika protected $paramNames = array('eu', 'us'); //Dann die einzelnen Werte defineren public static function S(){return new self('S', 44, 34);} public static function M(){return new self('M', 48, 38);} public static function L(){return new self('L', 54, 44);} public static function XL(){return new self('XL', 56, 46);} } //Ein Wert aussuchen $m = Size::M(); //Und auf die verschiedenen Werte zugreiffen echo "{$m->value} ist in EU-Grösse {$m->eu} und in US {$m->us}"; Ausgabe: M ist in EU-Grösse 48 und in US 38 ====Ableiten von Enums==== class Size extends Enum{ //Zuerst die Parameter defineren. In dem Fall die Grössenbez. für Europa un Amerika protected $paramNames = array('eu', 'us'); //Dann die einzelnen Werte defineren public static function S(){return new self('S', 44, 34);} public static function M(){return new self('M', 48, 38);} public static function L(){return new self('L', 54, 44);} public static function XL(){return new self('XL', 56, 46);} } //Die Size ableiten. Einige Werte überschreiben, einige Hinzufügen. //Die Parameter eu und us müssen nicht mehr neu definiert werden class ShortSize extends Size{ public static function S(){return new self('S', 46, 36);} public static function M(){return new self('M', 50, 40);} public static function XXL(){return new self('XXL', 62, 52);} } echo ShortSize::S()->eu; //46 echo ShortSize::L()->eu; //54 echo ShortSize::XXL()->eu; //62 ====Zugriff auf ein Enum dens nicht gibt==== function exceptionErrorHandler($errno, $errstr, $errfile, $errline ) { if($errno & ini_get('error_reporting')) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } } set_error_handler("exceptionErrorHandler"); try{ Enum::create('Sex', array('men' => 'm', 'women' => 'w')); $chield = Sex::getEnumKey('chield'); } catch(Exception $e){ echo "".$e->getMessage()."
\n"; echo nl2br($e->getTraceAsString()); }
no Enum found for 'chield' in 'Sex' #0 C:\xampp\htdocs\lib\enum\Enum.php(142): Enum->__getEnumKey('chield', 'Sex') #1 C:\xampp\htdocs\test\test3.php(20): Enum::getEnumKey('chield') #2 {main} =====Code===== ====Interface IEnum.php==== EnumValue) * @return array * @static */ public static function toArray($paramName = 'value'); /** * gibt alle Values als Array aus * @param $glue * @return String * @static */ public static function implode($glue, $paramName = 'value'); /** * O B J E K T - M E T H O D E N */ /** * constructer * @param $value * @param $paramlist */ public function __construct($value = NULL); /** * gibt den Enum als String zurück. Dies entspricht dem Value * @return String */ public function __toString(); /** * überprüft ob der Enum dem ausgewählten Enum entspricht * @param $var * @return Boolean */ public function equal($var); /** * gibt ein Enum anhand eines passenden Wertes zurück * @param $value * @param $className * @return Enum */ public function __getEnum($value, $className); } ?> ====Klasse Enum==== a * * // Enum erstellen mit einem Array. Der Key ist der Name der Funktion * createEnum('Enum2', array('A' => 'aa', 'B' => 'bb')); * echo Enum2::B(); //-> bb * * // Enum erstellen mit einem Array. Der Funktionsname ist gleich dem value * createEnum('Enum3', array('aaa', 'bbb')); * echo Enum3::aaa(); //-> aaa */ function createEnum($name, $enums){ $params = func_get_args(); return call_user_func_array(array('Enum', 'create'), $params); } /* * @example * class Enum1 extends AbstractEnum{ * // die ersten 3 Funktionen müssen so 1:1 übernommen werden * protected static function className(){return __CLASS__;} * public static function getInstance(){return new self();} * public static function getEnum($value){$e = new self(); return $e->createEnum($value);} * // Ab hier kommen die verschiedenen Enums * public static function A(){return new self('a');} * public static function B(){return new self('b');} * } * * $enum = Enum1::A(); * switch ($enum){ * case Enum1::A(): echo 'a'; break; * case Enum1::B(): echo 'b'; break; * default: echo 'default'; * } * if (Enum1::A()->equal($enum)) echo 'HalloA1'; * $enum = Enum1::getEnum('a'); */ class Enum implements IEnum{ static public $index; protected $paramNames = array(); /** * S T A T I S C H E M E T H O D E N */ /** * analog der Funktion createEnum($name, $enums) * @param String Name des Enums * @param Array oder Werteliste (siehe Beispiele) * @static * @example * // Enum erstellen mit einer beliebigen Anzahl Parameter * Enum::create('Enum1', 'a', 'b'); * echo Enum1::a(); //-> a * * // Enum erstellen mit einem Array. Der Key ist der Name der Funktion * Enum::create('Enum2', array('A' => 'aa', 'B' => 'bb')); * echo Enum2::B(); //-> bb * * // Enum erstellen mit einem Array. Der Funktionsname ist gleich dem Value * // zusätzlich als ist diese Klasse eine Ableitung von Enum2 * Enum::create('Enum3 extends Enum2', array('aaa', 'bbb')); * echo Enum3::aaa(); //-> aaa * echo Enum3::B(); //-> bb */ public static function create($name, $enums){ if(!is_array($enums)){ $enums = func_get_args(); $name = array_shift($enums); } // Falls kein extends mitgegeben wurde, die Enum-Klasse als Extends angeben if (!preg_match('/^[[:alnum:]_]+[ ]+extends[ ]+[[:alnum:]_]+$/', $name)){ $name = "{$name} extends ".__CLASS__; } // Classencode generieren $php = "class {$name}{\n"; foreach($enums as $key => $value){ if (is_numeric($key)) list($key, $value) = array($value, $value); preg_match_all('/[[:alnum:]_]+/i', $key, $keyElements); $key = implode('', $keyElements[0]); $php .= "public static function {$key}(){return new self('{$value}');}\n"; } $php .= "}\n"; eval($php); } /** * erstellt eine leere Instance der Enumklasse. Dies wird verwednet um auf * Funktionen wie getEnum() etc zuzugreiffen ohne einen bestimmten ENUM auszuwählen * @return Enum * @static */ public static function getInstance(){ $class = get_called_class(); return new $class(); } /** * Erstellt ein Enum anhand des Wertes * @param Wert * @return Enum * @static */ public static function getEnum($value){ return self::getInstance()->__getEnum($value, get_called_class()); } /** * Erstellt ein Enum anhand des Keys * @param $key * @return Enum * @static */ public static function getEnumKey($key){ return self::getInstance()->__getEnumKey($key, get_called_class()); } /** * wandelt die Enums in einen Array array('EnumName' => EnumValue) * @return array * @static */ public static function toArray($paramName = 'value'){ return self::getInstance()->__toArray(get_called_class(), 'value'); } /** * gibt alle Values als Array aus * @param $glue * @return String * @static */ public static function implode($glue, $paramName = 'value'){ return implode($glue, self::toArray()); } /** * O B J E K T - M E T H O D E N */ /** * constructer * @param $value * @param $paramlist */ public function __construct($value = NULL){ $this->params = func_get_args(); $this->value = array_shift($this->params); foreach($this->paramNames as $index => $name){ $this->$name = $this->params[$index]; } } /** * gibt den Enum als String zurück. Dies entspricht dem Value * @return String */ public function __toString(){ return (String) $this->value; } /** * überprüft ob der Enum dem ausgewählten Enum entspricht * @param $var * @return Boolean * @example * $enum = Enum1::A(); * if (Enum1::A()->equal($enum)) echo 'HalloA1'; */ public function equal($var){ return (Boolean) (is_a($var, get_called_class())) and ($var == $this); } /** * gibt ein Enum anhand eines passenden Wertes zurück * @example * $enum = Enum1::getInstance()->__getEnum('a'); * @param $value * @param $className * @return Enum */ public function __getEnum($value, $className){ if($func = array_search($value, $this->__toArray($className))) return $this->$func(); throw new Exception("no Enum found for '{$value}' in '{$className}'"); } /** * Erstellt ein Array mit allen Enums dieses Types * @example $array = Enum1::getInstance()->__toArray(); * @return array('EnumName' => 'value') */ protected function __toArray($className, $paramName = 'value'){ $enums = array_diff(get_class_methods($className), get_class_methods(__CLASS__)); $er = error_reporting(E_ERROR); foreach($enums as $func){ if($this->$func() instanceof self) $array[$func] = $this->$func()->$paramName; } error_reporting($er); return $array; } /** * gibt ein Enum anhand eines passenden Wertes zurück * @example * $enum = Enum1::getInstance()->__getEnum('a'); * @param $value * @access protected * @return Enum */ protected function __getEnumKey($key, $className){ if(array_key_exists($key, $this->__toArray($className))) return $this->$key(); throw new Exception("no Enum found for '{$key}' in '{$className}'"); } } ?> ====PHP52 Funktionen==== Unter PHP 5.3 ist die Funktion get_called_class() nicht bekannt. Diese ist aber sehr wichtig für die Enum-Klasse. In der Datei php52.php wird diese Funktion auch für PHP5.2 zr Verfügung gestellt. stack level too deep."); if (!isset($bt[$l]['type'])) { throw new Exception ('type not set'); } else switch ($bt[$l]['type']) { case '::': $lines = file($bt[$l]['file']); $i = 0; $callerLine = ''; do { $i++; $callerLine = $lines[$bt[$l]['line']-$i] . $callerLine; } while (stripos($callerLine,$bt[$l]['function']) === false); preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/', $callerLine, $matches); if (!isset($matches[1])) { // must be an edge case. throw new Exception ("Could not find caller class: originating method call is obscured."); } switch ($matches[1]) { case 'self': case 'parent': return get_called_class($bt,$l+1); default: return $matches[1]; } // won't get here. case '->': switch ($bt[$l]['function']) { case '__get': // edge case -> get class of calling object if (!is_object($bt[$l]['object'])) throw new Exception ("Edge case fail. __get called on non object."); return get_class($bt[$l]['object']); default: return $bt[$l]['class']; } default: throw new Exception ("Unknown backtrace method type"); } } } ?> ---- {{image class="left" alt="ico" url="images/icons/48/zip.png"}} {{tag>PHP}}