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