如何在运行时(动态地)创建一个PHP静态类属性?

13
我想做类似这样的事情:
public static function createDynamic(){
    $mydynamicvar = 'module'; 
    self::$mydynamicvar = $value;
}

并且能够从类内部访问该属性,使用:

$value = self::$module;
4个回答

12
我不确定为什么你想这样做,但这个方法是可行的。你需要像调用函数一样访问动态变量,因为PHP中尚未有 __getStatic() 魔术方法。

我不确定为什么您要这样做,但这个方法可行。由于 PHP 中尚不存在 __getStatic() 魔术方法,因此您必须像调用函数一样访问动态“变量”。

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

8

静态变量必须是类定义的一部分,因此您无法动态地创建它们。即使使用反射也不行:

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.

但这看起来非常像一个 XY问题。你可能不想在运行时向PHP类添加静态属性;你有一些用例可以通过其他方式实现。或者,如果可用的话,那种方式将是实现某些用例的最快方式。也许还有其他方法。
实际上,下面的用例又是解决某个更高级别问题的可能解决方案。重新审视高级别问题并以不同的方式进行重构/重新思考可能是值得的,也许可以跳过完全干预静态属性的需要。
我想在我的类内部有一个属性字典。
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');
}

我想将一些值与类关联起来,或者说:我想在别人的类内部创建一个属性字典。

这实际上发生在我身上,我在研究如何实现它时发现了这个问题。在我的工作流程的B点,我需要知道给定类被定义在哪个地方(“A”),以及由代码的哪一部分定义。最终,我将这些信息存储到一个由我的自动加载程序提供数据的数组中,并且还能够在类第一次加载时存储debug_backtrace()

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

我想要修改一个类的已有属性,而不是创建一个新的属性。

// 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);
}

2

静态属性必须在类定义中定义。因此,无法像常规属性一样动态创建真正的静态属性。

例如,如果您运行以下代码:

<?php

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

MyClass::createDynamic();

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

如果你遇到这个错误,那么可能是由于技术问题导致的。

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

请注意,当尝试设置属性而不是第14或15行时,错误发生在第8行(如果您只是错误地进行操作并且动态创建静态属性实际上是可能的话,您可能会期望这样)。

0
一个相关的问题是(在PHP 5.4.0及以上版本中)可以将各种独立的静态变量或常量声明包含在一起,并将它们组合成一个类声明。
以下是一个例子:
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接