我在尝试中使用了三个技巧:
private
对于具有私有非静态属性Foo
的类$bar
,我想禁止$this
之外的任何作用域修改其值。所以我这样做:
/** @property object $bar */
class Foo{
public function __get($k){
if($k === "bar") return $this->bar;
}
public function __set($k, $v){
if($k === "bar"){
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
if($trace[0]["object"] !== $this or $trace[0]["file"] !== __FILE__) throw new RuntimeException("Illegal access");
$this->bar = $v;
}
}
}
这应该(未经测试)不受三种访问的影响:
ReflectionClass::hasProperty()
检测它的存在: - )Closure::bind
Foo
,所以只要加载了正确的代码,我就不在乎了。假设没有写入任何文件的权限而且没有扩展来重新定义类方法,但是可以加载任意PHP代码,是否有任何方法可以更改此Foo->bar
属性?
答案 0 :(得分:1)
经过一些修补,我得出结论,你想要实现的目标是不可能的,也是毫无意义的。 我将解释原因。
一个类属性有三种可能的可见性:公共,受保护和私有。 如果是公开,您可以使用简单的分配修改该值:
npm install -g grunt-cli
我们可以用$foo->bar = "new value";
拦截这个吗?来自PHP Manual:
__ set()在将数据写入不可访问的属性时运行。
始终可以访问公开属性。
因此,根本没有机会拦截并进行检查,因为__set()
将不会被调用。
接下来,如果该属性是受保护或私有,则必须在该类中声明它,
这意味着您可以使用__set()
或ReflectionProperty
修改其值。
最后,您实际上可以通过将值存储在其他位置来确保调用Closure::bind
。
例如,在同一对象中的不同名称下,或甚至在另一个对象中。
不幸的是,无论你在哪里存储价值,我上面的解释都会再次适用,这就是为什么它没有意义。