1--TEST-- 2Lazy objects: property op on skipped property does not initialize object 3--FILE-- 4<?php 5 6class C { 7 public $a; 8 public int $b = 1; 9 public int $c; 10 public function __construct() { 11 var_dump(__METHOD__); 12 $this->a = 2; 13 } 14} 15 16function test(string $name, object $obj) { 17 printf("# %s:\n", $name); 18 19 $reflector = new ReflectionClass($obj); 20 $reflector->getProperty('a')->skipLazyInitialization($obj); 21 $reflector->getProperty('b')->skipLazyInitialization($obj); 22 $reflector->getProperty('c')->skipLazyInitialization($obj); 23 24 var_dump($obj); 25 var_dump($obj->a++); 26 var_dump($obj->b++); 27 try { 28 var_dump($obj->c++); 29 } catch (Error $e) { 30 printf("%s\n", $e->getMessage()); 31 } 32 var_dump($obj); 33} 34 35$reflector = new ReflectionClass(C::class); 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--EXPECTF-- 52# Ghost: 53object(C)#%d (2) { 54 ["a"]=> 55 NULL 56 ["b"]=> 57 int(1) 58 ["c"]=> 59 uninitialized(int) 60} 61NULL 62int(1) 63Typed property C::$c must not be accessed before initialization 64object(C)#%d (2) { 65 ["a"]=> 66 int(1) 67 ["b"]=> 68 int(2) 69 ["c"]=> 70 uninitialized(int) 71} 72# Proxy: 73object(C)#%d (2) { 74 ["a"]=> 75 NULL 76 ["b"]=> 77 int(1) 78 ["c"]=> 79 uninitialized(int) 80} 81NULL 82int(1) 83Typed property C::$c must not be accessed before initialization 84object(C)#%d (2) { 85 ["a"]=> 86 int(1) 87 ["b"]=> 88 int(2) 89 ["c"]=> 90 uninitialized(int) 91} 92