【问题标题】:Is there any way to set a private/protected static property using reflection classes?有没有办法使用反射类设置私有/受保护的静态属性?
【发布时间】:2011-09-20 20:53:38
【问题描述】:

我正在尝试为类的静态属性执行备份/恢复功能。我可以使用反射对象getStaticProperties() 方法获取所有静态属性及其值的列表。这将获取 privatepublic static 属性及其值。

问题是我在尝试使用反射对象setStaticPropertyValue($key, $value) 方法恢复属性时似乎没有得到相同的结果。 privateprotected 变量对于此方法不可见,因为它们对于 getStaticProperties() 可见。似乎不一致。

有没有办法使用反射类或其他任何方式设置私有/受保护的静态属性?

尝试过

class Foo {
    static public $test1 = 1;
    static protected $test2 = 2;

    public function test () {
        echo self::$test1 . '<br>';
        echo self::$test2 . '<br><br>';
    }

    public function change () {
        self::$test1 = 3;
        self::$test2 = 4;
    }
}

$test = new foo();
$test->test();

// Backup
$test2 = new ReflectionObject($test);
$backup = $test2->getStaticProperties();

$test->change();

// Restore
foreach ($backup as $key => $value) {
    $property = $test2->getProperty($key);
    $property->setAccessible(true);
    $test2->setStaticPropertyValue($key, $value);
}

$test->test();

【问题讨论】:

    标签: php reflection visibility


    【解决方案1】:

    为了访问类的私有/受保护属性,我们可能需要首先使用反射设置该类的可访问性。试试下面的代码:

    $obj         = new ClassName();
    $refObject   = new ReflectionObject( $obj );
    $refProperty = $refObject->getProperty( 'property' );
    $refProperty->setAccessible( true );
    $refProperty->setValue(null, 'new value');
    

    【讨论】:

    • ReflectionProperty::setValue() expects parameter 1 to be object, null given,你的回答建议我应该提供一个 null 但 php 抱怨:(
    • 请注意,-&gt;setValue(null, '...') 仅在设置的属性是 static 属性时才允许使用。如果你试图修改一个对象的属性,你需要提供一个真实的实例,否则 PHP 会报错ReflectionProperty::setValue() expects parameter 1 to be object, null given
    【解决方案2】:

    用于访问类的私有/受保护属性,使用反射,无需ReflectionObject 实例:

    对于静态属性:

    <?php
    $reflection = new \ReflectionProperty('ClassName', 'propertyName');
    $reflection->setAccessible(true);
    $reflection->setValue(null, 'new property value');
    


    对于非静态属性:

    <?php
    $instance = new SomeClassName();
    $reflection = new \ReflectionProperty(get_class($instance), 'propertyName');
    $reflection->setAccessible(true);
    $reflection->setValue($instance, 'new property value');
    

    【讨论】:

    • ReflectionProperty::setValue() expects parameter 1 to be object, null given 你的回答和@Shamee's 有同样的问题
    • 这在 PHP 5.6 中当然可以工作,并且文档表明这始终是它应该工作的方式(参见:php.net/manual/en/reflectionproperty.setvalue.php),所以不确定为什么它不适用于 @ThorSummoner
    • 很好的答案,只是想添加一个可能有一天会帮助其他人的注释,在设置私有属性时,您必须传递该属性所属的类名。如果属性属于父类,你可以做\ReflectionProperty(get_parent_class($instance), 'propertyName') 否则你应该做\ReflectionProperty(\namespace\ParentClass::class,'propertyName') 如果私有属性属于当前类,那么\ReflectionProperty($instance, 'propertyName')
    【解决方案3】:

    您还可以实现类内部方法来更改对象属性访问设置,然后使用$instanve-&gt;properyname = ..... 设置值:

    public function makeAllPropertiesPublic(): void
    {
        $refClass = new ReflectionClass(\get_class($this));
        $props = $refClass->getProperties();
        foreach ($props as $property) {
            $property->setAccessible(true);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 2014-10-13
      相关资源
      最近更新 更多