1--TEST-- 2Initialization can only happen from private scope 3--FILE-- 4<?php 5 6class A { 7 public readonly int $prop; 8 9 public function initPrivate() { 10 $this->prop = 3; 11 } 12} 13class B extends A { 14 public function initProtected() { 15 $this->prop = 2; 16 } 17} 18 19$test = new B; 20try { 21 $test->prop = 1; 22} catch (Error $e) { 23 echo $e->getMessage(), "\n"; 24} 25$test->initProtected(); 26var_dump($test); 27 28$test = new B; 29$test->initPrivate(); 30var_dump($test->prop); 31 32// Rebinding bypass works. 33$test = new B; 34(function() { 35 $this->prop = 1; 36})->bindTo($test, A::class)(); 37var_dump($test->prop); 38 39class C extends A { 40 public readonly int $prop; 41} 42 43$test = new C; 44$test->initPrivate(); 45var_dump($test->prop); 46 47class X { 48 public function initFromParent() { 49 $this->prop = 1; 50 } 51} 52class Y extends X { 53 public readonly int $prop; 54} 55 56$test = new Y; 57$test->initFromParent(); 58var_dump($test); 59 60?> 61--EXPECTF-- 62Cannot modify protected(set) readonly property A::$prop from global scope 63object(B)#%d (1) { 64 ["prop"]=> 65 int(2) 66} 67int(3) 68int(1) 69int(3) 70object(Y)#%d (1) { 71 ["prop"]=> 72 int(1) 73} 74