1--TEST-- 2foreach over hooked properties 3--FILE-- 4<?php 5 6#[AllowDynamicProperties] 7class ByRef { 8 public $plain = 'plain'; 9 private $_virtualByRef = 'virtualByRef'; 10 public $virtualByRef { 11 &get { 12 echo __METHOD__, "\n"; 13 return $this->_virtualByRef; 14 } 15 set { 16 echo __METHOD__, "\n"; 17 $this->_virtualByRef = $value; 18 } 19 } 20 public $virtualSetOnly { 21 set { 22 echo __METHOD__, "\n"; 23 } 24 } 25 public function __construct() { 26 $this->dynamic = 'dynamic'; 27 } 28} 29 30#[AllowDynamicProperties] 31class ByVal extends ByRef { 32 private $_virtualByVal = 'virtualByVal'; 33 public $virtualByVal { 34 get { 35 echo __METHOD__, "\n"; 36 return $this->_virtualByVal; 37 } 38 set { 39 echo __METHOD__, "\n"; 40 $this->_virtualByVal = $value; 41 } 42 } 43 public $backed = 'backed' { 44 get { 45 echo __METHOD__, "\n"; 46 return $this->backed; 47 } 48 set { 49 echo __METHOD__, "\n"; 50 $this->backed = $value; 51 } 52 } 53 public string $backedUninitialized { 54 get { 55 echo __METHOD__, "\n"; 56 $this->backedUninitialized ??= 'backedUninitialized'; 57 return $this->backedUninitialized; 58 } 59 set { 60 echo __METHOD__, "\n"; 61 $this->backedUninitialized = $value; 62 } 63 } 64} 65 66function testByRef($object) { 67 foreach ($object as $prop => &$value) { 68 echo "$prop => $value\n"; 69 $value = strtoupper($value); 70 } 71 unset($value); 72 var_dump($object); 73} 74 75function testByVal($object) { 76 foreach ($object as $prop => $value) { 77 echo "$prop => $value\n"; 78 $object->{$prop} = strtoupper($value); 79 } 80 var_dump($object); 81} 82 83testByVal(new ByVal); 84testByVal(new ByRef); 85testByRef(new ByRef); 86 87?> 88--EXPECTF-- 89ByVal::$virtualByVal::get 90virtualByVal => virtualByVal 91ByVal::$virtualByVal::set 92ByVal::$backed::get 93backed => backed 94ByVal::$backed::set 95ByVal::$backedUninitialized::get 96backedUninitialized => backedUninitialized 97ByVal::$backedUninitialized::set 98plain => plain 99ByRef::$virtualByRef::get 100virtualByRef => virtualByRef 101ByRef::$virtualByRef::set 102dynamic => dynamic 103object(ByVal)#%d (6) { 104 ["plain"]=> 105 string(5) "PLAIN" 106 ["_virtualByRef":"ByRef":private]=> 107 string(12) "VIRTUALBYREF" 108 ["_virtualByVal":"ByVal":private]=> 109 string(12) "VIRTUALBYVAL" 110 ["backed"]=> 111 string(6) "BACKED" 112 ["backedUninitialized"]=> 113 string(19) "BACKEDUNINITIALIZED" 114 ["dynamic"]=> 115 string(7) "DYNAMIC" 116} 117plain => plain 118ByRef::$virtualByRef::get 119virtualByRef => virtualByRef 120ByRef::$virtualByRef::set 121dynamic => dynamic 122object(ByRef)#%d (3) { 123 ["plain"]=> 124 string(5) "PLAIN" 125 ["_virtualByRef":"ByRef":private]=> 126 string(12) "VIRTUALBYREF" 127 ["dynamic"]=> 128 string(7) "DYNAMIC" 129} 130plain => plain 131ByRef::$virtualByRef::get 132virtualByRef => virtualByRef 133dynamic => dynamic 134object(ByRef)#%d (3) { 135 ["plain"]=> 136 string(5) "PLAIN" 137 ["_virtualByRef":"ByRef":private]=> 138 string(12) "VIRTUALBYREF" 139 ["dynamic"]=> 140 string(7) "DYNAMIC" 141} 142