如何使用PHP中的反射通过引用获取属性值?

时间:2011-09-08 09:06:22

标签: php reflection

假设你有一个这样声明的类:

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是原始数组的副本。

提前致谢!

3 个答案:

答案 0 :(得分:8)

从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/

详细解释了技术和最终用例

答案 1 :(得分:1)

我怕你不能。 ReflectionProperty::getValue必须通过引用返回才能实现,但事实并非如此。

答案 2 :(得分:0)

你可以从原始的$ 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)并通过reflection和setAccessible从回调中调用它。只要在原始类中定义此方法,它就可以访问所有私有成员。