动态地将私有属性添加到对象

时间:2014-01-22 19:57:49

标签: php oop reflection

如果您有以下代码:

<?php

class Foo { public $attribute; }

$o = new Foo();
$o->bar = true;

?>

PHP自动为该对象创建动态公共属性。

是否有可能添加动态私有属性?或者在运行时使用Reflection?

将它们设置为私有

每次有人试图在我的班级中设置任何属性时,都需要调用我的__set方法。我可以将所有属性设置为私有,但是,我有在此类中动态添加的属性,并且当自动添加属性时,它具有公共可见性。

这可以防止调用__set方法。如何在收到值时调用__set动态属性?

实际上,ReflectionProperty类上有一个名为setAccessible()的方法。我会采用与此方法相反的方法。

1 个答案:

答案 0 :(得分:3)

在当前版本的PHP中,这似乎不可行。

虽然ReflectionProperty::setAccessible() 采用布尔参数,但它所做的更改只允许Reflection本身访问/不访问该值。它实际上并没有改变实际属性的可访问性。

作为保持动态属性私有的hacky解决方法,请考虑使用专用私有数组中实际不存在的__set存储属性。示例代码:

class Test {

    private $foo;
    public $bar;
    private $_properties;

    public function __get($prop) {
        if(property_exists($this, $prop))
            return $this->$prop;
        if(array_key_exists($prop, $this->_properties))
            return $this->_properties[$prop];
    }

    public function __set($prop, $value) {
        if(!property_exists($this, $prop)) {
            $this->_properties[$prop] = $value;
            echo 'SetDynamic: ', $prop, "\n";
            return;
        }
        $this->$prop = $value; 
        echo 'Set: ', $prop, "\n";
    }

}

从PHP交互式提示符运行:

php > $t = new Test;
php > $t->foo = 1;
Set: foo
php > $t->foo = 2;
Set: foo
php > $t->bar = 1;
php > $t->testorama = 1;
SetDynamic: testorama
php > $t->testorama = 2;
SetDynamic: testorama

虽然这可以确保外部访问总是通过您的__get__set方法,但它会给内部使用带来问题,因为你现在总是有两个地方来检查动态属性。这就是为什么这是一个hackish解决方法而不是真正的解决方案。