1--TEST--
2Lazy objects: hooked property fetch does not initialize object if hook does not observe object state
3--FILE--
4<?php
5
6class C {
7    public $a {
8        get { return $this->a; }
9        set($value) { $this->a = $value; }
10    }
11    public int $b = 1;
12
13    public function __construct(int $a) {
14        var_dump(__METHOD__);
15        $this->a = $a;
16        $this->b = 2;
17    }
18}
19
20function test(string $name, object $obj) {
21    printf("# %s:\n", $name);
22
23    var_dump($obj);
24    var_dump($obj->a);
25    var_dump($obj);
26}
27
28$reflector = new ReflectionClass(C::class);
29
30$obj = $reflector->newLazyGhost(function ($obj) {
31    var_dump("initializer");
32    $obj->__construct(1);
33});
34
35test('Ghost', $obj);
36
37$obj = $reflector->newLazyProxy(function ($obj) {
38    var_dump("initializer");
39    return new C(1);
40});
41
42test('Proxy', $obj);
43
44--EXPECTF--
45# Ghost:
46lazy ghost object(C)#%d (0) {
47  ["b"]=>
48  uninitialized(int)
49}
50string(11) "initializer"
51string(14) "C::__construct"
52int(1)
53object(C)#%d (2) {
54  ["a"]=>
55  int(1)
56  ["b"]=>
57  int(2)
58}
59# Proxy:
60lazy proxy object(C)#%d (0) {
61  ["b"]=>
62  uninitialized(int)
63}
64string(11) "initializer"
65string(14) "C::__construct"
66int(1)
67lazy proxy object(C)#%d (1) {
68  ["instance"]=>
69  object(C)#%d (2) {
70    ["a"]=>
71    int(1)
72    ["b"]=>
73    int(2)
74  }
75}
76