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