Created
July 8, 2012 12:16
PHP: Possible LazyLoad approach allowing PHP5.4 optimizations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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