1--TEST-- 2Lazy objects: Initializer effects are reverted after exception (dynamic properties) 3--FILE-- 4<?php 5 6#[AllowDynamicProperties] 7class C { 8 public $a = 1; 9 public int $b = 2; 10 public int $c; 11} 12 13function test(string $name, object $obj) { 14 $reflector = new ReflectionClass(C::class); 15 16 printf("# %s:\n", $name); 17 18 (new ReflectionProperty(C::class, 'c'))->setRawValueWithoutLazyInitialization($obj, 0); 19 20 try { 21 $reflector->initializeLazyObject($obj); 22 } catch (Exception $e) { 23 printf("%s\n", $e->getMessage()); 24 } 25 26 var_dump($obj); 27 printf("Is lazy: %d\n", $reflector->isUninitializedLazyObject($obj)); 28} 29 30$reflector = new ReflectionClass(C::class); 31 32$obj = $reflector->newLazyGhost(function ($obj) { 33 var_dump("initializer"); 34 $obj->a = 3; 35 $obj->b = 4; 36 $obj->c = 5; 37 $obj->d = 6; 38 throw new Exception('initializer exception'); 39}); 40 41test('Ghost', $obj); 42 43$obj = $reflector->newLazyProxy(function ($obj) { 44 var_dump("initializer"); 45 $obj->a = 3; 46 $obj->b = 4; 47 $obj->c = 5; 48 $obj->d = 6; 49 throw new Exception('initializer exception'); 50}); 51 52// Initializer effects on the proxy are not reverted 53test('Proxy', $obj); 54 55--EXPECTF-- 56# Ghost: 57string(11) "initializer" 58initializer exception 59lazy ghost object(C)#%d (1) { 60 ["b"]=> 61 uninitialized(int) 62 ["c"]=> 63 int(0) 64} 65Is lazy: 1 66# Proxy: 67string(11) "initializer" 68initializer exception 69lazy proxy object(C)#%d (4) { 70 ["a"]=> 71 int(3) 72 ["b"]=> 73 int(4) 74 ["c"]=> 75 int(5) 76 ["d"]=> 77 int(6) 78} 79Is lazy: 1 80