有没有办法使用反射类设置私有/受保护的静态属性?
Posted
技术标签:
【中文标题】有没有办法使用反射类设置私有/受保护的静态属性?【英文标题】:Is there any way to set a private/protected static property using reflection classes? 【发布时间】:2011-09-20 20:53:38 【问题描述】:我正在尝试为类的静态属性执行备份/恢复功能。我可以使用反射对象getStaticProperties()
方法获取所有静态属性及其值的列表。这将获取 private
和 public static
属性及其值。
问题是我在尝试使用反射对象setStaticPropertyValue($key, $value)
方法恢复属性时似乎没有得到相同的结果。 private
和 protected
变量对于此方法不可见,因为它们对于 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();
【问题讨论】:
【参考方案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 抱怨:(
请注意,->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->properyname = .....
设置值:
public function makeAllPropertiesPublic(): void
$refClass = new ReflectionClass(\get_class($this));
$props = $refClass->getProperties();
foreach ($props as $property)
$property->setAccessible(true);
【讨论】:
以上是关于有没有办法使用反射类设置私有/受保护的静态属性?的主要内容,如果未能解决你的问题,请参考以下文章