假设您有一个这样声明的类:
class DummyObject{
public $attr;
public function __construct(){
$this->attr=array('val_1','val_2','val_3');
}
}
这样做:
$obj=(new DummyObject1());
$attr=&$obj->attr;
你将得到一个对$attr
的引用,因此在数组中所做的任何修改也将在DummyObject $obj实例中进行。
现在,最后一个问题。使用反射,我如何获得对存储在$attr
中的数组的引用而不是副本?我试过了,但没有成功:
$obj=(new DummyObject());
$reflector = new ReflectionObject($obj);
$reflectorProperty = $reflector->getProperty('attr');
$propertyValue=$reflectorProperty->getValue($ref);
实际上,$attr
是原始数组的副本。
提前感谢!
从PHP 5.4开始,您可以在没有反射的情况下执行此操作:
class Kitchen
{
private $yummy = 'cake';
}
$reader = function & ($object, $property) {
$value = & Closure::bind(function & () use ($property) {
return $this->$property;
}, $object, $object)->__invoke();
return $value;
};
$kitchen = new Kitchen();
$cake = & $reader($kitchen, 'yummy');
$cake = 'sorry, I ate it!';
var_dump($kitchen);
这是由于PHP 5.4能够在运行时切换闭包的作用域。
您可以在http://3v4l.org/sZMt1
找到一个运行的示例我实际上在http://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/
恐怕不行。ReflectionProperty::getValue
必须通过引用返回,这是可能的,它没有。
您可以从原始的$obj中获得它,您可以通过"use"语句传递给回调
$propertyValue = $obj->{$reflectorProperty->getName()};
或者如果你为私有成员使用公共getter/setter,你可以
$propertyName = $reflectorProperty->getName();
$methodName = 'get' . ucfirst($propertyName);
if (method_exists($obj, $methodName)) {
$propertyValue = call_user_func([ $object, $methodName ]);
} elseif (isset($obj->{$propertyName}) {
$propertyValue = $this->{$propertyName};
} else {
$propertyValue = null;
}
另一个解决方案是定义私有(或公共)方法$obj->getProperty($name),并通过反射和setAccessible从回调中调用它。一旦在原始类中定义了这个方法,它就可以访问所有的私有成员。