2011-09-08 75 views
1

假设你已经宣布这样一个类:如何使用PHP中的反射来引用属性值?

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

在此先感谢!

+1

请问你的意图是什么详细阐述了该技术,并最终使用情况?我的意思是,你有对象,属性名称和属性是公共的。为什么你需要用反射来获得财产? – Yoshi

+0

我猜想的唯一目的是让代码变得复杂。 – xdazz

+0

我的意图不是让代码变得复杂。 我有一个对象,它可以引用其他对象,使用json_decode从JSON中的HTTP响应中获取,我需要遍历所有属性以递归地对存储字符串的所有属性进行一些更改。 – jLuengas

回答

1

恐怕你不能。 ReflectionProperty::getValue将不得不通过引用返回,以使其成为可能,而不是。

+0

我怀疑那个。但我注意到,如果该值是关联数组或另一个对象,那么'ReflectionProperty :: getValue'将返回引用,所以也许可能是以相同方式检索arrayas引用的一种方法。 – jLuengas

+0

@jLu我不知道你的意思。从我所看到的getValue永远不能返回引用。 – Artefacto

+0

我尝试过使用指向对象实例和关联数组的属性,然后'ReflectionProperty :: getValue'返回引用,因为可以在原始对象中看到返回对象的更改。当属性指向一个数组时,这种行为是不一样的。 感谢您的关注! – jLuengas

0

您可以从原来的$ OBJ可以传递通过回调得到它“使用”的语句

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

7

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

+4

*那么......丑陋的......但是......必须...... upvote ...... arggggggh。* – rdlowrey

+0

注意:作品也与公共属性:) – Ocramius

+0

有什么理由让你的外层函数也是闭包?这似乎是没有必要的。 https://3v4l.org/4tAqu – donquixote