Есть ли способ динамически создавать константы класса? Я знаю, это звучит немного странно, но позвольте мне объяснить, что я пытаюсь сделать:
const
Может быть, что-то вроде этого:
class myEnum extends SplEnum { public static function init () { $myNameValuePair = DB_Functions::get_enum_list(); foreach ( $myNameValuePair as $name => $value) { $const = array ( self , $name ); $const = $value; } } }
Я понимаю, что это на самом деле не работает, поскольку оно не устанавливает константные переменные CONST, а скорее статические. Может быть, моя идея – это волосы, а у вас есть лучшая техника. В любом случае, любой метод достижения конечной цели очень ценится.
ОБНОВИТЬ
Я думаю, что было бы полезно немного понять мои цели, потому что я думаю, что вполне возможно, что мое использование констант не очень хорошее. В принципе, я хочу достичь, это типично для требований перечислимого списка:
Сигнатуры функции ограничения . Я хочу иметь возможность запросить «набор» значений в качестве входных данных для функции. Например:
public function do_something (ENUM_Types $ type) {}
Простой и компактный . Разрешите простой и компактный синтаксис при использовании в коде. Например, с использованием констант я могу написать условное утверждение, например:
if ($ my_var === ENUM_Types :: TypeA) {}
Динамическое перечисление . Я бы хотел, чтобы это перечисление управлялось через интерфейс и хранилось в базе данных (я использую экраны администратора WordPress для этого, если кто-то заботится). Во время выполнения этот «список» следует вытащить из БД и сделать доступным для кода как перечисление (или аналогичную структуру, которая достигает целей выше).
Оберните значения «enum» в одноэлементном режиме и реализуйте (нестатический) магический метод __get
:
<?php class DynamicEnums { private static $singleton; private $enum_values; public static function singleton() { if (!self::$singleton) { self::$singleton = new DynamicEnums(); } return self::$singleton; } function __construct() { $this->enum_values = array( //fetch from somewhere 'one' => 'two', 'buckle' => 'my shoe!', ); } function __get($name) { return $this->enum_values[$name]; //or throw Exception? } public static function values() { return self::singleton()->enum_values; //warning... mutable! } }
Для бонусных очков создайте функцию (non-OO), которая возвращает singleton:
function DynamicEnums() { return DynamicEnums::singleton(); }
Потребители «DynamicEnums» выглядели бы так:
echo DynamicEnums::singleton()->one; echo DynamicEnums()->one; //can you feel the magic? print_r(DynamicEnums::values());
[edit] Больше enum-like.
В: Есть ли способ динамически создавать константы класса?
Ответ «Да», но не делайте этого 🙂
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: Сигнатуры функции Constrain. Я хочу иметь возможность запросить «набор» значений в качестве входных данных для функции. Например:
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: Динамическое перечисление. Я бы хотел, чтобы это перечисление управлялось через интерфейс и хранилось в базе данных (я использую экраны администратора WordPress для этого, если кто-то заботится). Во время выполнения этот «список» следует вытащить из БД и сделать доступным для кода как перечисление (или аналогичную структуру, которая достигает целей выше).
Вы можете инициализировать перечисление, передав массив в EnumFactory::create($class, $constants)
:
EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));
Вы можете сделать что-то вроде Const = $$ constant. Тогда вы можете установить $ contant = что угодно. ИЛИ вы можете использовать защищенное свойство, так как вы хотите, чтобы он был динамическим, а константы – нет. Пример:
class Foo { protected $test = ''; function set($bar){ $this->test = $bar; } function get($bar){ return $this->test; } } $foobar = new Foo(); $foobar->set('test'); echo $foobar->get('test');
Я не рекомендую, но eval () … пожалуйста, не надо.
Я изменил автозагрузчики, чтобы автоматически определять типы исключений, которые отсутствуют или ошибочно написаны. Причина. Вы можете поймать неперехваченное исключение, но вы не можете восстановить его из PHP_FATAL при создании экземпляра в классе исключения.