1--TEST-- 2Lazy objects: Foreach initializes object 3--FILE-- 4<?php 5 6#[AllowDynamicProperties] 7class C { 8 public int $a; 9 private int $_b; 10 public int $b { 11 &get { $ref = &$this->_b; return $ref; } 12 } 13 public function __construct(bool $addDynamic = true) { 14 var_dump(__METHOD__); 15 $this->a = 1; 16 $this->_b = 2; 17 if ($addDynamic) { 18 $this->c = 3; 19 $this->d = 4; 20 unset($this->c); 21 } 22 } 23} 24 25$reflector = new ReflectionClass(C::class); 26 27function test(string $name, object $obj) { 28 printf("# %s:\n", $name); 29 foreach ($obj as $prop => $value) { 30 var_dump($prop, $value); 31 } 32 foreach ($obj as $prop => &$value) { 33 var_dump($prop, $value); 34 } 35} 36 37$obj = $reflector->newLazyGhost(function ($obj) { 38 var_dump("initializer"); 39 $obj->__construct(); 40}); 41 42test('Ghost', $obj); 43 44$obj = $reflector->newLazyProxy(function ($obj) { 45 var_dump("initializer"); 46 return new C(); 47}); 48 49test('Proxy', $obj); 50 51$obj = $reflector->newLazyGhost(function ($obj) { 52 var_dump("initializer"); 53 $obj->__construct(addDynamic: false); 54}); 55 56test('Ghost (no dynamic)', $obj); 57 58$obj = $reflector->newLazyProxy(function ($obj) { 59 var_dump("initializer"); 60 return new C(addDynamic: false); 61}); 62 63test('Proxy (no dynamic)', $obj); 64 65print "# Proxy of proxy (initialization)\n"; 66 67$obj = $reflector->newLazyProxy(function ($obj) use (&$obj2, $reflector) { 68 var_dump("initializer"); 69 return $obj2 = new C(); 70}); 71$reflector->initializeLazyObject($obj); 72$reflector->resetAsLazyProxy($obj2, function () { 73 return new C(); 74}); 75 76test('Proxy of proxy', $obj); 77 78print "# Ghost (init exception):\n"; 79 80$obj = $reflector->newLazyGhost(function ($obj) { 81 throw new \Exception("initializer"); 82}); 83 84try { 85 var_dump(json_encode($obj)); 86} catch (\Exception $e) { 87 printf("%s: %s\n", $e::class, $e->getMessage()); 88} 89 90print "# Proxy (init exception):\n"; 91 92$obj = $reflector->newLazyProxy(function ($obj) { 93 throw new \Exception("initializer"); 94}); 95 96try { 97 var_dump(json_encode($obj)); 98} catch (\Exception $e) { 99 printf("%s: %s\n", $e::class, $e->getMessage()); 100} 101 102--EXPECT-- 103# Ghost: 104string(11) "initializer" 105string(14) "C::__construct" 106string(1) "a" 107int(1) 108string(1) "b" 109int(2) 110string(1) "d" 111int(4) 112string(1) "a" 113int(1) 114string(1) "b" 115int(2) 116string(1) "d" 117int(4) 118# Proxy: 119string(11) "initializer" 120string(14) "C::__construct" 121string(1) "a" 122int(1) 123string(1) "b" 124int(2) 125string(1) "d" 126int(4) 127string(1) "a" 128int(1) 129string(1) "b" 130int(2) 131string(1) "d" 132int(4) 133# Ghost (no dynamic): 134string(11) "initializer" 135string(14) "C::__construct" 136string(1) "a" 137int(1) 138string(1) "b" 139int(2) 140string(1) "a" 141int(1) 142string(1) "b" 143int(2) 144# Proxy (no dynamic): 145string(11) "initializer" 146string(14) "C::__construct" 147string(1) "a" 148int(1) 149string(1) "b" 150int(2) 151string(1) "a" 152int(1) 153string(1) "b" 154int(2) 155# Proxy of proxy (initialization) 156string(11) "initializer" 157string(14) "C::__construct" 158# Proxy of proxy: 159string(14) "C::__construct" 160string(1) "a" 161int(1) 162string(1) "b" 163int(2) 164string(1) "d" 165int(4) 166string(1) "a" 167int(1) 168string(1) "b" 169int(2) 170string(1) "d" 171int(4) 172# Ghost (init exception): 173Exception: initializer 174# Proxy (init exception): 175Exception: initializer 176