PHP中的动态常量?

PHP中的动态常量?,php,Php,有没有办法动态创建类的常量?我知道这听起来有点奇怪,但让我解释一下我想做什么: 我有一个枚举类,它的属性由staticconst定义定义 这个类扩展了PHP SplEnum类 我不想在代码中输入这些定义中的每一个,而是希望有一个静态初始化器进入数据库并提取枚举值 也许是这样的: class myEnum extends SplEnum { public static function init () { $myNameValuePair = DB_Functions:

有没有办法动态创建类的常量?我知道这听起来有点奇怪,但让我解释一下我想做什么:

  • 我有一个枚举类,它的属性由static
    const
    定义定义
  • 这个类扩展了PHP SplEnum类
  • 我不想在代码中输入这些定义中的每一个,而是希望有一个静态初始化器进入数据库并提取枚举值
也许是这样的:

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;
        }
    }
}
我认识到这实际上不会起作用,因为它不会设置常量,而是静态变量。也许我的整个想法都是胡思乱想的,还有更好的方法。无论如何,实现最终目标的任何方法都是非常值得赞赏的

更新

我认为更清楚一点我的目标可能会有帮助,因为我认为完全有可能我对常量的使用不好。基本上,我想要实现的是枚举列表的典型要求:

  • 约束函数签名。我希望能够请求一组值作为函数的输入。例如:

    公共函数do_something(枚举类型$type){}

  • 简单紧凑。在代码中使用时,允许使用简单紧凑的语法。例如,通过使用常量,我可以编写一个条件语句,如下所示:

    如果($my_var==ENUM_Types::TypeA){}

  • 动态枚举。我想通过前端管理这个枚举,并将其存储在数据库中(我使用wordpress管理屏幕,以防有人关心)。在运行时,这个“列表”应该从数据库中取出,并作为枚举(或实现上述目标的类似结构)提供给代码


  • 您可以执行类似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恢复。

    将“enum”值包装在一个单例中,并实现(非静态)magic
    \u 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!
      }
    }
    
    “dynamicinums”的消费者看起来像:

    echo DynamicEnums::singleton()->one;
    echo DynamicEnums()->one;            //can you feel the magic?
    print_r(DynamicEnums::values());
    
    [编辑]更像枚举

    问:有没有一种方法可以动态创建类的常量

    答案是“是”,但不要这样做:)


    下一个问题

    Q:约束函数签名。我希望能够请求一组值作为函数的输入。例如:
    公共函数do_something(ENUM_Types$type){}

    根据,在这种情况下,
    $type
    is必须是
    枚举类型
    类的实例。但对于常量,这是不可能的(它们不能包含对象)

    但是等等。。。我们可以使用这样的技巧:

    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
    
    然后我们可以使用“类型暗示”:


    问:简单紧凑。在代码中使用时,允许使用简单紧凑的语法。例如,通过使用常量,我可以编写一个条件语句,比如:
    if($my_var===ENUM_Types::TypeA){}

    您可以使用以下形式的伪常量值:

    if (darkSide::FOO === 1) {}
    

    Q:动态枚举。我想通过前端管理这个枚举,并将其存储在数据库中(我使用wordpress管理屏幕,以防有人关心)。在运行时,这个“列表”应该从数据库中取出,并作为枚举(或实现上述目标的类似结构)提供给代码

    通过将数组传递给
    EnumFactory::create($class,$constants)
    ,可以初始化枚举:


    根据定义,常数不能是动态的。必须将其设置为文字值。使用受保护的属性并将其像Psuedo常量一样使用如何?您能描述一下您在回答中的意思吗?我?我只是说常数可以静态使用,所以不能在构造函数方法中使用它们。实际上,他可能想要的只是一个可以设置并保护的属性。因为在他的使用中,它更像是一个受保护的属性,而不是一个常量。“…你不能在构造函数方法中实现它们”…那么
    self:$var=“value”呢?这样做可能没有意义,但这是可能的。根据定义,常数不可能是动态的。为什么不使用静态变量呢?是的,我知道,这就是为什么我说它“可能看起来有点奇怪”。我会更新一下这个问题,让它更清楚地说明我想要达到的目标。换句话说。。。你不需要动态常量,你需要的是动态枚举。使用一个充当注册表的类怎么样?我刚刚读了标题,想了想“wtf”,谢谢。如果你愿意走在黑暗面(又名评估面),很高兴看到你如何做到这一点。这看起来不错。我相信它符合我的所有要求。非常感谢你的魔力。(^)可悲的是,我用这种方法遇到了很大的限制。。。也就是说,如果您将一组helper函数构建到一个基类中,然后将其子类化为各种枚举,您会发现它们都共享来自静态基类的单例。该死,该死,该死。我需要找到一种方法来摆脱我所处的困境。需要帮助动态调用静态方法吗?
    
    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 (darkSide::FOO === 1) {}
    
    EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));