繁体   English   中英

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

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

我想做这样的事情:

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

并且能够从班级内访问该物业

$value = self::$module;

我不知道你为什么要这样做,但这是有效的。 您必须像函数一样访问动态“变量”,因为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();

静态变量必须是类定义的一部分,因此您无法动态创建它们。 甚至没有反射

 chuck at manchuck dot com 2 years ago 

请务必注意,调用ReflectionClass::setStaticPropertyValue将不允许您向类添加新的静态属性。

但这看起来非常像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);
}

必须在类定义中定义静态属性。 因此,无法像常规属性那样动态创建实际静态属性。

例如,如果你运行这个:

<?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行是如何发生错误的(如果您只是做错了并且动态创建静态属性实际上是可能的话,您可能会想到)。

可能的相关问题(在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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM