How do I create a PHP static class property at runtime (dynamically)?

前端 未结 4 1896
遥遥无期
遥遥无期 2021-02-19 12:47

I\'d like to do something like this:

public static function createDynamic(){
    $mydynamicvar = \'module\'; 
    self::$mydynamicvar = $value;
}
4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-19 13:38

    static variables must be part of the class definition, so you can't create them dynamically. Not even with Reflection:

    chuck at manchuck dot com                                             2 years ago
    

    It is important to note that calling ReflectionClass::setStaticPropertyValue will not allow you to add new static properties to a class.

    But this looks very much like a XY Problem. You probably don't really want to add static properties to a PHP class at runtime; you have some use case that could be fulfilled also that way. Or that way would be the fastest way, were it available, to fulfill some use case. There well might be other ways.

    Actually the use cases below are yet again possible solutions to some higher level problem. It might be worth it to reexamine the high level problem and refactor/rethink it in different terms, maybe skipping the need of meddling with static properties altogether.

    I want a dictionary of properties inside my class.

    trait HasDictionary {
        private static $keyValueDictionary = [ ];
    
        public static function propget($name) {
            if (!array_key_exists($name, static::$keyValueDictionary) {
                return null;
            }
            return static::$keyValueDictionary[$name];
        }
    
        public static function propset($name, $value) {
            if (array_key_exists($name, static::$keyValueDictionary) {
                $prev = static::$keyValueDictionary[$name];
            } else {
                $prev = null;
            }
            static::$keyValueDictionary[$name] = $value;
            return $prev;
        }
    }
    
    
    class MyClass
    {
        use Traits\HasDictionary;
    
        ...$a = self::propget('something');
    
        self::propset('something', 'some value');
    }
    

    I want to associate some values to a class, or: I want a dictionary of properties inside some one else's class.

    This actually happened to me and I found this question while investigating ways of doing it. I needed to see, in point B of my workflow, in which point ("A") a given class had been defined, and by what other part of code. In the end I stored that information into an array fed by my autoloader, and ended up being able to also store the debug_backtrace() at the moment of class first loading.

    // Solution: store values somewhere else that you control.
    
    class ClassPropertySingletonMap {
        use Traits\HasDictionary; // same as before
    
        public static function setClassProp($className, $prop, $value) {
            return self::propset("{$className}::{$prop}", $value);
        }
    
        public static function getClassProp($className, $prop) {
            return self::propget("{$className}::{$prop}");
        }
    }
    
    // Instead of
    // $a = SomeClass::$someName;
    // SomeClass::$someName = $b;
    
    // we'll use
    // $a = ClassPropertySingletonMap::getClassProp('SomeClass','someName');
    // ClassPropertySingletonMap::setClassProp('SomeClass','someName', $b);
    

    I want to change, not create, an existing property of a class.

    // Use Reflection. The property is assumed private, for were it public
    // you could do it as Class::$property = $whatever;
    
    function setPrivateStaticProperty($class, $property, $value) {
        $reflector = new \ReflectionClass($class);
        $reflector->getProperty($property)->setAccessible(true);
        $reflector->setStaticPropertyValue($property, $value);
        $reflector->getProperty($property)->setAccessible(false);
    }
    

提交回复
热议问题