My team is using lazyloading techniques to load sub-objects from our database. To do this we're using the magic __get() method and making a database call. All of our properties are protected so the __get method gets called from outside of the object but our issue is that it doesn't get called from within the object without using $this->__get($name);
So my question is: Is it possible to force __get() to be called with the normal chaining operator even from within the object?
If I want to chain object access I currently have to do:
$this->__get('subObject')->__get('subObject')->__get('subObject')
Is it possible to write the following, but have it still call __get()?
$this->subObject->subObject->subObject
Thanks, Jordan
Jordan,
PHP won't call the __get()
method unless the property is inaccessible—either because it doesn't exist, or because of visibility. When the property is hidden from the calling scope the __get() method is called because the property is inaccessible. When the property is referenced and is available to the calling scope, __get() will never fire. (It's not meant to fire for an existing/accessible property.)
To work around this you have to rename your internal properties. Either prefix them with a name, underscore, or store them in a common array parameter with a special name. The following is somewhat contrived, but it ought to demonstrate how you can deal with this situation.
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);
}
}
}
See: http://www.php.net/manual/language.oop5.overloading.php#object.get