1--TEST--
2Lazy objects: Foreach initializes object
3--FILE--
4<?php
5
6class C {
7    public int $a;
8    public int $b;
9    public function __construct() {
10        var_dump(__METHOD__);
11        $this->a = 1;
12        $this->b = 2;
13    }
14}
15
16$reflector = new ReflectionClass(C::class);
17
18print "# Ghost:\n";
19
20$obj = $reflector->newLazyGhost(function ($obj) {
21    var_dump("initializer");
22    $obj->__construct();
23});
24
25foreach ($obj as $prop => $value) {
26    var_dump($prop, $value);
27}
28
29print "# Ghost (by ref):\n";
30
31$obj = $reflector->newLazyGhost(function ($obj) {
32    var_dump("initializer");
33    $obj->__construct();
34});
35
36foreach ($obj as $prop => &$value) {
37    var_dump($prop, $value);
38}
39
40print "# Proxy:\n";
41
42$obj = $reflector->newLazyProxy(function ($obj) {
43    var_dump("initializer");
44    return new C();
45});
46
47foreach ($obj as $prop => $value) {
48    var_dump($prop, $value);
49}
50
51print "# Proxy (by ref):\n";
52
53$obj = $reflector->newLazyProxy(function ($obj) {
54    var_dump("initializer");
55    return new C();
56});
57
58foreach ($obj as $prop => &$value) {
59    var_dump($prop, $value);
60}
61
62print "# Ghost (init failure)\n";
63
64$fail = true;
65$obj = $reflector->newLazyGhost(function ($obj) use (&$fail) {
66    if ($fail) {
67        throw new Exception("initializer");
68    } else {
69        var_dump("initializer");
70        $obj->__construct();
71    }
72});
73
74try {
75    foreach ($obj as $prop => $value) {
76        var_dump($prop, $value);
77    }
78} catch (Exception $e) {
79    printf("%s: %s\n", $e::class, $e->getMessage());
80}
81
82$fail = false;
83foreach ($obj as $prop => $value) {
84    var_dump($prop, $value);
85}
86
87print "# Ghost (init failure, by ref)\n";
88
89$fail = true;
90$obj = $reflector->newLazyGhost(function ($obj) use (&$fail) {
91    if ($fail) {
92        throw new Exception("initializer");
93    } else {
94        var_dump("initializer");
95        $obj->__construct();
96    }
97});
98
99try {
100    foreach ($obj as $prop => &$value) {
101        var_dump($prop, $value);
102    }
103} catch (Exception $e) {
104    printf("%s: %s\n", $e::class, $e->getMessage());
105}
106
107$fail = false;
108foreach ($obj as $prop => &$value) {
109    var_dump($prop, $value);
110}
111
112?>
113--EXPECT--
114# Ghost:
115string(11) "initializer"
116string(14) "C::__construct"
117string(1) "a"
118int(1)
119string(1) "b"
120int(2)
121# Ghost (by ref):
122string(11) "initializer"
123string(14) "C::__construct"
124string(1) "a"
125int(1)
126string(1) "b"
127int(2)
128# Proxy:
129string(11) "initializer"
130string(14) "C::__construct"
131string(1) "a"
132int(1)
133string(1) "b"
134int(2)
135# Proxy (by ref):
136string(11) "initializer"
137string(14) "C::__construct"
138string(1) "a"
139int(1)
140string(1) "b"
141int(2)
142# Ghost (init failure)
143Exception: initializer
144string(11) "initializer"
145string(14) "C::__construct"
146string(1) "a"
147int(1)
148string(1) "b"
149int(2)
150# Ghost (init failure, by ref)
151Exception: initializer
152string(11) "initializer"
153string(14) "C::__construct"
154string(1) "a"
155int(1)
156string(1) "b"
157int(2)
158