Skip to content

Instantly share code, notes, and snippets.

@juzna
Created June 25, 2011 15:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save juzna/1046613 to your computer and use it in GitHub Desktop.
Save juzna/1046613 to your computer and use it in GitHub Desktop.
Lazy-loading for PHP
<?php
class Address {
public $street;
public $town;
}
class Customer {
public $id;
public $name;
public $address;
}
class Payment {
public $amount;
public $customer;
}
$db = getDatabase();
$payment = $db->load('Payment', 123);
/*
$payment containts:
amount = 100;
customer = class Customer {
id = 5;
name = uninitialized;
address = uninitialized;
}
}
*/
echo $payment->customer->name; // DB layer will load customer info
// or
echo $payment->customer->address->town; // DB layer will load customer & address info
<?php
/**
* Example of possible lazy-loading in PHP
* Added new special value called "uninitialized". When a property with this value is being read from object,
* __initialize($propertyName) magic method is invoked to lazy-load the value.
*/
class Foo {
private $bar = uninitialized;
private $lol = "lol";
public $pub = uninitialized;
public $blank = uninitialized;
function getBar() {
echo "Getter method bar, ";
return $this->bar;
}
function getLol() {
echo "Getter method lol, ";
return $this->lol;
}
function getPub() {
echo "Getter method pub, ";
return $this->pub;
}
function __get($name) {
echo "Magic getter $name, ";
return $this->$name;
}
function __initialize($name) {
if($name !== 'blank') {
echo "Initializing $name, ";
$this->$name = "I'm $name";
}
else {
echo "Trying to initialize blank, ";
}
}
function clean() {
$this->bar = $this->lol = $this->pub = uninitialized;
}
}
// __initialize will be called only once, on first access
$foo = new Foo;
var_dump($foo->getBar()); // Getter method bar, Initializing bar, string(7) "I'm bar"
var_dump($foo->getBar()); // Getter method bar, string(7) "I'm bar"
// magic __get is called first, and inside it's initialized
$foo = new Foo;
var_dump($foo->bar); // Magic getter bar, Initializing bar, string(7) "I'm bar"
var_dump($foo->bar); // Magic getter bar, string(7) "I'm bar"
$foo->clean();
var_dump($foo->bar); // Magic getter bar, Initializing bar, string(7) "I'm bar"
var_dump($foo->bar); // Magic getter bar, string(7) "I'm bar"
// lazy-loading of public properties
$foo = new Foo;
var_dump($foo->pub); // Initializing pub, string(7) "I'm pub"
// normal value remains as expected
$foo = new Foo;
var_dump($foo->getLol()); // Getter method lol, string(3) "lol"
// variable which cannot be initialized
$foo = new Foo;
var_dump($foo->blank); // Trying to initialize blank, undefined
var_dump($foo->blank); // Trying to initialize blank, undefined
@fprochazka
Copy link

Makes no sense to re-assign "uninitialized" again.

@juzna
Copy link
Author

juzna commented Jun 25, 2011

@hosiplan Usually not and it's not the main idea here, and I don't see a reason why not to allow it.

@fprochazka
Copy link

Because it makes no sense :) You cant un-initialize a property, only unset it.

@juzna
Copy link
Author

juzna commented Jun 25, 2011

@hosiplan: ok, forget about un-initializing, I mean the rest

@md2perpe
Copy link

@hosiplan: As I understand it, uninitialized is a hypothetical extra constant/value that @juzna want to use to mark uninitialized values. It's not exactly the same as unset()ing a variable.

@fprochazka
Copy link

I get that. But when you think about it. Such an operation makes no sense. I get @juzna's reasons to hate Proxy Pattern, even do i disagree with @juzna, but making properties unitialized again makes no sense, why would anyone wanna do that?

This uninitialized is damn magical itself, making it possible to unitialize it again would make it Gandalf or something.

Much better would be to create REAL support for proxy objects, because that's what this is about. Like in smalltalk.

And change it to

private lazy $bar;

for chists sake...

@juzna
Copy link
Author

juzna commented Jun 26, 2011

The real reason why I want uninitialized to be assign-able could be seen in example.php of this Gist. You may have a class Customer, which has just normal properties (not with a lazy keyword as proposed by @hosiplan, nor with predefined uninitialized value). You can new that class and all properties will have nulls, as normally. Nothing changes here.

First time a new type of value would be used is when you load a $payment from database. DB layer will create instance of Customer class, assign proper id to it's $id property and uninitialized to all other properties. Then, when you access such a property for the first time, DB layer can lazy-load the whole customer instance.

You, as a programmer, don't have to ever use this special value. It will just be used for you by the DB layer, which might be easier with this support in PHP lang.

@fprochazka
Copy link

@juzna Hmm, makes sense. Still don't like it. Better make real support for proxy objects...

@md2perpe
Copy link

One approach of lazyload: https://gist.github.com/1049509

@juzna
Copy link
Author

juzna commented Jun 27, 2011 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment