如果您有以下代码:
<?php
class Foo { public $attribute; }
$o = new Foo();
$o->bar = true;
?>
PHP自动为该对象创建动态公共属性。
是否有可能添加动态私有属性?或者在运行时使用Reflection?
将它们设置为私有每次有人试图在我的班级中设置任何属性时,都需要调用我的__set
方法。我可以将所有属性设置为私有,但是,我有在此类中动态添加的属性,并且当自动添加属性时,它具有公共可见性。
这可以防止调用__set
方法。如何在收到值时调用__set
动态属性?
实际上,ReflectionProperty类上有一个名为setAccessible()的方法。我会采用与此方法相反的方法。
答案 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解决方法而不是真正的解决方案。