使用->对受保护属性调用__get();操作符


Call __get() on protected properties with -> operator?

我的团队正在使用lazyloading技术从我们的数据库加载子对象。要做到这一点,我们使用神奇的__get()方法并进行数据库调用。我们所有的属性都是受保护的所以__get方法可以从对象外部调用但我们的问题是,如果不使用$this->__get($name);

,它就不能从对象内部调用

所以我的问题是:是否有可能强制__get()使用正常的链接操作符调用,甚至从对象内部?

如果我想链接对象访问,我现在必须这样做:

$this->__get('subObject')->__get('subObject')->__get('subObject') 

是否有可能写下面的代码,但仍然调用__get()?

$this->subObject->subObject->subObject

谢谢,约旦

Jordan,

PHP不会调用__get()方法,除非该属性不可访问——要么是因为它不存在,要么是因为可见性。当属性从调用范围中隐藏时,__get()方法被调用,因为该属性是不可访问的。当属性被引用并且对调用范围可用时,__get()将永远不会触发。(这并不意味着触发一个现有的/可访问的属性。)

要解决这个问题,您必须重命名您的内部属性。可以使用名称、下划线作为前缀,或者将它们存储在具有特殊名称的公共数组参数中。下面的内容有些做作,但它应该能说明你如何处理这种情况。
class MyObject {
   protected $lazyloads = array();
   protected function lazyload($relation) {
     // ...
   }
   public function __get($key) {
     if (isset($this->lazyloads[$key]) {
       return $this->lazyloads[$key];
     } else {
       return $this->lazyload($key);
     }
   }
}

见:http://www.php.net/manual/language.oop5.overloading.php object.get

@Robert K或者(例如):

class A
{
    protected $objects = array();
    public function __get($name)
    {
        if(isset($this->objects[$name])) {
            return $this->objects[$name];
        }
        return null; // or throw 'Exception
    }
}
class B
{
    protected $objects = array();
    public function __get($name)
    {
        // for example: $this->objects[$name] is type of A
        if(isset($this->objects[$name])) {
            return $this->objects[$name];
        }
        return null; // or throw 'Exception
    }
}

每个返回的对象必须有一个魔术方法__get来返回一个对象