1--TEST--
2Lazy objects: fetch skipped property does not initialize object
3--FILE--
4<?php
5
6class C {
7    public $a;
8    public int $b = 1;
9    public int $c;
10
11    public function __construct(int $a) {
12        var_dump(__METHOD__);
13        $this->a = $a;
14        $this->b = 2;
15    }
16}
17
18function test(string $name, object $obj) {
19    printf("# %s:\n", $name);
20
21    $reflector = new ReflectionClass($obj);
22    $reflector->getProperty('a')->skipLazyInitialization($obj);
23    $reflector->getProperty('b')->skipLazyInitialization($obj);
24    $reflector->getProperty('c')->skipLazyInitialization($obj);
25
26    var_dump($obj);
27    var_dump($obj->a);
28    var_dump($obj->b);
29    try {
30        var_dump($obj->c);
31    } catch (Error $e) {
32        printf("%s\n", $e->getMessage());
33    }
34    var_dump($obj);
35}
36
37$reflector = new ReflectionClass(C::class);
38
39$obj = $reflector->newLazyGhost(function ($obj) {
40    var_dump("initializer");
41    $obj->__construct(1);
42});
43
44test('Ghost', $obj);
45
46$obj = $reflector->newLazyProxy(function ($obj) {
47    var_dump("initializer");
48    return new C(1);
49});
50
51test('Proxy', $obj);
52
53--EXPECTF--
54# Ghost:
55object(C)#%d (2) {
56  ["a"]=>
57  NULL
58  ["b"]=>
59  int(1)
60  ["c"]=>
61  uninitialized(int)
62}
63NULL
64int(1)
65Typed property C::$c must not be accessed before initialization
66object(C)#%d (2) {
67  ["a"]=>
68  NULL
69  ["b"]=>
70  int(1)
71  ["c"]=>
72  uninitialized(int)
73}
74# Proxy:
75object(C)#%d (2) {
76  ["a"]=>
77  NULL
78  ["b"]=>
79  int(1)
80  ["c"]=>
81  uninitialized(int)
82}
83NULL
84int(1)
85Typed property C::$c must not be accessed before initialization
86object(C)#%d (2) {
87  ["a"]=>
88  NULL
89  ["b"]=>
90  int(1)
91  ["c"]=>
92  uninitialized(int)
93}
94