【问题标题】:Is it possible to truly limit access of this private property?是否有可能真正限制对该私有财产的访问?
【发布时间】:2017-05-22 16:44:12
【问题描述】:

我在尝试中使用了三个技巧:

  • 反射不能与动态类属性一起使用
  • 访问动态类属性时必须调用__get() 或__set()
  • debug_backtrace() 可以用来模拟类似于private 的东西

对于具有私有非静态属性$bar 的类Foo,我想禁止$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;
        }
    }
}

这应该(未经测试)不受三种访问的影响:

  • 直接访问
    • debug_backtrace() 检查调用上下文是否来自 $this。不允许在 $this 之外直接访问。
  • 反射属性
    • PHP 致命错误:未捕获的 ReflectionException:属性栏不存在
    • 反射不适用于动态属性。它甚至没有通过ReflectionClass::hasProperty() 检测到它的存在 :-)
  • Closure::bind
    • 未测试,但我相信 debug_backtrace() 应该返回与 FILE 不同的“文件”,而是定义闭包的文件。我只有Foo的正确用法,所以只要加载了正确的代码,我就不管了。

假设没有写任何文件的权限,也没有重新定义类方法的扩展名,但是可以加载任意PHP代码,有没有办法改变这个Foo->bar属性?

【问题讨论】:

  • 您试图阻止从课堂外更改$bar 属性?一个简单的private $bar 有什么问题?
  • @RayRadin 正如我已经提到的,它可以通过反射访问。我试图通过动态属性防止反射触及它。
  • 我明白了。所以你想要像private $bar 这样的行为而不在对象中声明它?

标签: php oop reflection visibility pocketmine


【解决方案1】:

经过一番修修补补,我得出的结论是,您要实现的目标是不可能的,而且毫无意义。 我会解释原因。

类属性有 3 种可能的可见性:publicprotectedprivate。 如果是public,可以通过简单的赋值来修改值:

$foo->bar = "new value";

我们可以用__set() 拦截这个吗?来自PHP Manual

__set() 在将数据写入不可访问的属性时运行。

public 属性始终是可访问的。 因此,根本没有机会拦截并进行检查,因为不会调用__set()

接下来,如果属性是protectedprivate,你必须在类中声明它, 这意味着您可以使用ReflectionPropertyClosure::bind 来修改其值。

最后,您实际上可以通过将值存储在其他地方来确保调用__set()。 例如,在同一个对象中使用不同的名称,甚至在另一个对象中。 不幸的是,无论您将值存储在哪里,我上面的解释都再次适用,这就是为什么它没有意义。

【讨论】:

  • 不错的递归!因此,如果我们想保存生成另一个名称的盐,我们首先必须将该盐保存在私有的某个地方:P 我意识到局部变量是真正私有的。让我们看看我是否可以通过一些回溯扩展来访问它:D Jk。我知道这真的毫无意义。
  • @PEMapModder 是的,但我不知道这是否可能,所以这是一个很好的心理锻炼。我喜欢它。
猜你喜欢
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 2016-07-23
  • 1970-01-01
  • 2020-07-14
  • 2016-11-17
  • 2023-03-17
相关资源
最近更新 更多