1--TEST-- 2Lazy objects: setRawValueWithoutLazyInitialization() preserves readonly semantics 3--FILE-- 4<?php 5 6class C { 7 public readonly int $a; 8 public $b; 9} 10 11function test(string $name, object $obj) { 12 printf("# %s\n", $name); 13 14 $reflector = new ReflectionClass(C::class); 15 $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, 1); 16 try { 17 $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, 2); 18 } catch (\Error $e) { 19 printf("%s: %s\n", $e::class, $e->getMessage()); 20 } 21 22 var_dump(!$reflector->isUninitializedLazyObject($obj)); 23 var_dump($obj); 24} 25 26$reflector = new ReflectionClass(C::class); 27$obj = $reflector->newLazyGhost(function () { 28 throw new \Exception('initializer'); 29}); 30 31test('Ghost', $obj); 32 33$obj = $reflector->newLazyProxy(function () { 34 throw new \Exception('initializer'); 35}); 36 37test('Proxy', $obj); 38 39?> 40--EXPECTF-- 41# Ghost 42Error: Cannot modify readonly property C::$a 43bool(false) 44lazy ghost object(C)#%d (1) { 45 ["a"]=> 46 int(1) 47} 48# Proxy 49Error: Cannot modify readonly property C::$a 50bool(false) 51lazy proxy object(C)#%d (1) { 52 ["a"]=> 53 int(1) 54} 55