How do I create a PHP static class property at run

2019-04-05 07:44发布

I'd like to do something like this:

public static function createDynamic(){
    $mydynamicvar = 'module'; 
    self::$mydynamicvar = $value;
}

and be able to access the property from within the class with

$value = self::$module;

3条回答
太酷不给撩
2楼-- · 2019-04-05 08:10

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);
}
查看更多
何必那么认真
3楼-- · 2019-04-05 08:11

Static properties must be defined in the class definition. Therefore, real static properties cannot be created dynamically like regular properties.

For example, if you run this:

<?php

class MyClass
{
    public static function createDynamic()
    {
        $mydynamicvar = 'module';
        self::$mydynamicvar = $value;
    }
}

MyClass::createDynamic();

var_dump(MyClass::$mydynamicvar);
var_dump(MyClass::$module);

...you'll get this error

Fatal error: Access to undeclared static property: MyClass::$mydynamicvar test.php on line 8

Notice how the error occurs on line 8 when trying to set the property instead of line 14 or 15 (as you might expect if you were simply doing it wrong and dynamically creating static properties was actually possible).

查看更多
我命由我不由天
4楼-- · 2019-04-05 08:31

I don't know exactly why you would want to do this, but this works. You have to access the dynamic 'variables' like a function because there is no __getStatic() magic method in PHP yet.

class myclass{
    static $myvariablearray = array();

    public static function createDynamic($variable, $value){
        self::$myvariablearray[$variable] = $value;
    }

    public static function __callstatic($name, $arguments){
        return self::$myvariablearray[$name];
    }
}

myclass::createDynamic('module', 'test');
echo myclass::module();
查看更多
登录 后发表回答