Q: クラスの定数を動的に作成する方法はありますか?
答えは「はい」ですが、そうしないでください:)
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;
次の問題...
Q: 関数のシグネチャを制限します。関数への入力として値の「セット」を要求できるようにしたいと考えています。例えば: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());
Q: シンプルでコンパクト。コードで使用する場合は、シンプルでコンパクトな構文を使用できます。たとえば、定数を使用して、次のような条件ステートメントを書くことができます。if ( $my_var === ENUM_Types::TypeA ) {}
次の形式で疑似定数の値を使用できます。
if (darkSide::FOO === 1) {}
Q: 動的列挙。この列挙をフロントエンドで管理し、データベースに保存したいと思います(誰かが気にする場合に備えて、これにはワードプレスの管理画面を使用しています)。実行時に、この「リスト」は DB から取り出され、列挙 (または上記の目標を達成する同様の構造) としてコードで使用できるようにする必要があります。
に配列を渡すことで、列挙を開始できますEnumFactory::create($class, $constants)
。
EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));