问:有没有办法动态创建类的常量?
答案是“是”,但不要那样做:)
class EnumFactory {
public static function create($class, array $constants) {
$declaration = '';
foreach($constants as $name => $value) {
$declaration .= 'const ' . $name . ' = ' . $value . ';';
}
eval("class $class { $declaration }");
}
}
EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));
echo darkSide::FOO . ' ' . darkSide::BAR;
下一个问题...
问:约束函数签名。我希望能够请求一组值作为函数的输入。例如:public function do_something ( ENUM_Types $type ) {}
根据手册,在这种情况下$type
必须是ENUM_Types
该类的一个实例。但是对于常量是不可能的(它们不能包含对象)。
但是等等......我们可以使用这样的技巧:
class Enum {
protected static $_constantToClassMap = array();
protected static function who() { return __CLASS__; }
public static function registerConstants($constants) {
$class = static::who();
foreach ($constants as $name => $value) {
self::$_constantToClassMap[$class . '_' . $name] = new $class();
}
}
public static function __callStatic($name, $arguments) {
return self::$_constantToClassMap[static::who() . '_' . $name];
}
}
class EnumFactory {
public static function create($class, $constants) {
$declaration = '';
foreach($constants as $name => $value) {
$declaration .= 'const ' . $name . ' = ' . $value . ';';
}
eval("class $class extends Enum { $declaration protected static function who() { return __CLASS__; } }");
$class::registerConstants($constants);
}
}
EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));
EnumFactory::create('aaa', array('FOO' => 1, 'BAR' => 2));
echo (aaa::BAR() instanceof aaa) ? 'Yes' : 'No'; // Yes
echo (aaa::BAR() instanceof darkSide) ? 'Yes' : 'No'; // No
之后我们可以使用“类型提示”:
function doSomething(darkSide $var) {
echo 'Bu!';
}
doSomething(darkSide::BAR());
doSomething(aaa::BAR());
问:简单紧凑。在代码中使用时允许使用简单而紧凑的语法。例如,使用常量我可能会写一个条件语句,例如:if ( $my_var === ENUM_Types::TypeA ) {}
您可以以这种形式使用伪常量的值:
if (darkSide::FOO === 1) {}
问:动态枚举。我希望通过前端管理这个枚举并存储在数据库中(我正在使用 wordpress 管理屏幕,以防万一有人关心)。在运行时,应该将这个“列表”从数据库中取出,并作为枚举(或实现上述目标的类似结构)提供给代码。
您可以通过将数组传递给来初始化您的枚举EnumFactory::create($class, $constants)
:
EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));