Dynamic constants in PHP?

前端 未结 4 2193
迷失自我
迷失自我 2021-02-09 08:36

Is there a way to create a class\'s constants dynamically? I know this sounds a bit odd but let me explain what I\'m trying to do:

  • I have a Enum class who\'s attri
4条回答
  •  [愿得一人]
    2021-02-09 09:02

    Q: Is there a way to create a class's constants dynamically?

    The answer is 'Yes', but don't do that :)

    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;
    

    Next question...

    Q: Constrain function signatures. I want to be able to ask for a "set" of values as an input to a function. For instance: public function do_something ( ENUM_Types $type ) {}

    According to the manual, in that case $type is must be an instance of the ENUM_Types class. But for constant it is impossible (they can't contain objects).

    But wait... We can use such trick:

    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
    

    And after that we can use a "type hinting":

    function doSomething(darkSide $var) {
        echo 'Bu!';
    }
    
    doSomething(darkSide::BAR());
    doSomething(aaa::BAR());
    

    Q: Simple and Compact. Allow for a simple and compact syntax when used in code. For instance with the use of constants I might write a conditional statement something like: if ( $my_var === ENUM_Types::TypeA ) {}

    You can use values of your pseudo-constants in such form:

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

    Q: Dynamic enumeration. I'd like this enumeration to be managed through the frontend and stored in the database (I'm using wordpress admin screens for this in case anyone cares). At run time this "list" should be pulled out of the DB and made available to the code as an enumeration (or similar structure that achieves the goals above).

    You can init your enumeration by passing array to the EnumFactory::create($class, $constants):

    EnumFactory::create('darkSide', array('FOO' => 1, 'BAR' => 2));
    

提交回复
热议问题