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

♀尐吖头ヾ 提交于 2020-01-01 08:33:01

问题


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;

回答1:


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();



回答2:


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:


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:


A related problem that IS possible (in PHP 5.4.0 and up) is to include various separate groups of static variable or constant declarations and group them together into one class declaration.

Here is an example:

trait Added1 // This can be located in one Include file
    {
    static
    $x="hello"; // Can declare more variables here
    }
trait Added2 // This can be located in another Include file
    {
    static
    $y="world"; // Can declare more variables here
    }
class G // Global constant and variable declarations class
    {
    use Added1, Added2; // Combines all variable declarations
    }

echo G::$x." ".G::$y; // Shows "hello world" on the web page


来源:https://stackoverflow.com/questions/9843362/how-do-i-create-a-php-static-class-property-at-runtime-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!