--TEST-- Lazy objects: recursive magic property fetch initializes object if magic method observes object state --FILE-- $name; } } function test(string $name, object $obj) { printf("# %s:\n", $name); var_dump($obj); var_dump($obj->magic); var_dump($obj); } $reflector = new ReflectionClass(C::class); $obj = $reflector->newLazyGhost(function ($obj) { var_dump("initializer"); $obj->__construct(); }); test('Ghost', $obj); $obj = $reflector->newLazyProxy(function ($obj) { var_dump("initializer"); return new C(); }); test('Proxy', $obj); --EXPECTF-- # Ghost: lazy ghost object(C)#%d (0) { ["a"]=> uninitialized(int) } string(11) "initializer" string(14) "C::__construct" Warning: Undefined property: C::$magic in %s on line %d NULL object(C)#%d (1) { ["a"]=> int(1) } # Proxy: lazy proxy object(C)#%d (0) { ["a"]=> uninitialized(int) } string(11) "initializer" string(14) "C::__construct" Warning: Undefined property: C::$magic in %s on line %d NULL lazy proxy object(C)#%d (1) { ["instance"]=> object(C)#%d (1) { ["a"]=> int(1) } }