Reputation: 71
Suppose you have a class declared like this:
class DummyObject{
public $attr;
public function __construct(){
$this->attr=array('val_1','val_2','val_3');
}
}
Doing this:
$obj=(new DummyObject1());
$attr=&$obj->attr;
You'll get a reference to $attr
so any modifications made in the array will be made also in DummyObject $obj instance.
And now, finally the question. Using reflection, ¿how can I get a reference to the array stored in $attr
and not a copy?. I've tried this without success:
$obj=(new DummyObject());
$reflector = new ReflectionObject($obj);
$reflectorProperty = $reflector->getProperty('attr');
$propertyValue=$reflectorProperty->getValue($ref);
In fact,$attr
is a copy of original array.
Thanks in advance!
Upvotes: 3
Views: 2122
Reputation: 25431
Since PHP 5.4 you can do this without reflection:
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);
This is thanks to the ability of PHP 5.4 to switch the scope of a closure at runtime.
You can find a running example at http://3v4l.org/sZMt1
I actually explained the technique and eventual use cases in detail at http://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/
Upvotes: 9
Reputation: 453
You can get it from original $obj that you can pass to callback via "use" statement
$propertyValue = $obj->{$reflectorProperty->getName()};
Or if you use public getters/setters for private members you can
$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;
}
Another solution is to define private (or public) method $obj->getProperty($name) and call it from your callback through reflection and setAccessible. As soon as this method defined in original class it has access to all private members.
Upvotes: 0
Reputation: 97805
I'm afraid you can't. ReflectionProperty::getValue
would have to return by reference for that to be possible, which it doesn't.
Upvotes: 1