1--TEST-- 2Lazy objects: hooked property fetch does not initialize object if hook does not observe object state 3--FILE-- 4<?php 5 6class C { 7 public $a { 8 get { return $this->a; } 9 set($value) { $this->a = $value; } 10 } 11 public int $b = 1; 12 13 public function __construct(int $a) { 14 var_dump(__METHOD__); 15 $this->a = $a; 16 $this->b = 2; 17 } 18} 19 20function test(string $name, object $obj) { 21 printf("# %s:\n", $name); 22 23 var_dump($obj); 24 var_dump($obj->a); 25 var_dump($obj); 26} 27 28$reflector = new ReflectionClass(C::class); 29 30$obj = $reflector->newLazyGhost(function ($obj) { 31 var_dump("initializer"); 32 $obj->__construct(1); 33}); 34 35test('Ghost', $obj); 36 37$obj = $reflector->newLazyProxy(function ($obj) { 38 var_dump("initializer"); 39 return new C(1); 40}); 41 42test('Proxy', $obj); 43 44--EXPECTF-- 45# Ghost: 46lazy ghost object(C)#%d (0) { 47 ["b"]=> 48 uninitialized(int) 49} 50string(11) "initializer" 51string(14) "C::__construct" 52int(1) 53object(C)#%d (2) { 54 ["a"]=> 55 int(1) 56 ["b"]=> 57 int(2) 58} 59# Proxy: 60lazy proxy object(C)#%d (0) { 61 ["b"]=> 62 uninitialized(int) 63} 64string(11) "initializer" 65string(14) "C::__construct" 66int(1) 67lazy proxy object(C)#%d (1) { 68 ["instance"]=> 69 object(C)#%d (2) { 70 ["a"]=> 71 int(1) 72 ["b"]=> 73 int(2) 74 } 75} 76