Skip to content

Instantly share code, notes, and snippets.

@rodneyrehm
Created July 8, 2012 12:16
PHP: Possible LazyLoad approach allowing PHP5.4 optimizations
<?php
// Transparent Lazy Loading as used up to PHP 5.3
class Foo {
public function __get($name) {
if ($name == 'lazy') {
echo "<getting>\n";
$this->lazy = $this->getLazy();
return $this->lazy;
}
throw new Exception("yadda yadda");
}
public function __set($name, $value) {
if ($name == 'lazy') {
echo "<setting>\n";
$this->lazy = $value;
return;
}
throw new Exception("yadda yadda");
}
public function getLazy() {
echo "<loading>\n";
// dummy, this would obviously be replaced by some proper object
$t = new StdClass();
$t->foobar = 'Hello World';
return $t;
}
}
// will work fine
$foo = new Foo();
var_dump(
$foo->lazy->foobar,
$foo->lazy->foobar
);
// no difference to above example
$foo = new Foo();
$lazy = $foo->lazy;
var_dump(
$lazy->foobar,
$lazy->foobar
);
<?php
// Transparent Lazy Loading to be used from PHP 5.4
class Foo {
public $lazy;
public function __construct() {
$this->lazy = new LazyLoader($this, 'lazy', 'getLazy');
}
public function getLazy() {
// dummy, this would obviously be replaced by some proper object
$t = new StdClass();
$t->foobar = 'Hello World';
return $t;
}
}
class LazyLoader {
private $object;
private $container;
private $property;
private $creator;
public function __construct($container, $property, $creator) {
$this->container = $container;
$this->property = $property;
$this->creator = $creator;
}
private function load() {
// just tell us what's going on…
echo "<lazyloading>\n";
// load lazy
$o = $this->container->{$this->creator}();
// assign lazy loaded object
$this->container->{$this->property} = $o;
// kill circular reference
$this->container = null;
// remember object
$this->object = $o;
return $o;
}
public function __isset($name) {
if (!$this->object) {
$this->load();
}
return isset($this->object->$name);
}
public function __get($name) {
if (!$this->object) {
$this->load();
}
return $this->object->$name;
}
public function __set($name, $value) {
if (!$this->object) {
$this->load();
}
$this->object->$name = $value;
}
public function __call($name, $arguments) {
if (!$this->object) {
$this->load();
}
return call_user_func_array(array($this->object, $name), $arguments);
}
}
// will work fine
$foo = new Foo();
var_dump(
$foo->lazy->foobar,
$foo->lazy->foobar
);
// will work, because we kept a reference in LazyLoader
// it will always pass through the magic methods, so
// should in fact be avoided like pestilence
$foo = new Foo();
$lazy = $foo->lazy;
var_dump(
$lazy->foobar,
$lazy->foobar
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment