1--TEST--
2Reflection and property_exists()
3--FILE--
4<?php
5
6#[AllowDynamicProperties]
7class A
8{
9    public    $a = 1;
10    protected $b = 2;
11    private   $c = 3;
12
13    public    $empty;
14    public    $init = 1;
15
16    function __toString()
17    {
18        return 'obj(' . get_class($this) . ')';
19    }
20
21    static function test($oc, $props)
22    {
23        echo '===' . __CLASS__ . "===\n";
24        foreach($props as $p2) {
25            echo $oc, '::$' , $p2, "\n";
26            var_dump(property_exists($oc, $p2));
27        }
28    }
29}
30
31class B extends A
32{
33    private   $c = 4;
34
35    static function test($oc, $props)
36    {
37        echo '===' . __CLASS__ . "===\n";
38        foreach($props as $p2) {
39            echo $oc, '::$' , $p2, "\n";
40            var_dump(property_exists($oc, $p2));
41        }
42    }
43}
44
45class C extends B
46{
47    private   $d = 5;
48
49    static function test($oc, $props)
50    {
51        echo '===' . __CLASS__ . "===\n";
52        foreach($props as $p2) {
53            echo $oc, '::$' , $p2, "\n";
54            var_dump(property_exists($oc, $p2));
55        }
56    }
57}
58
59$oA = new A;
60$oA->e = 6;
61
62$oC = new C;
63
64$pc = array($oA, 'A', 'B', 'C', $oC);
65$pr = array('a', 'b', 'c', 'd', 'e');
66
67foreach($pc as $p1) {
68    if (is_object($p1)) {
69        $p1->test($p1, $pr);
70    } else {
71        $r = new ReflectionMethod($p1, 'test');
72        $r->invoke(NULL, $p1, $pr);
73    }
74    echo "===GLOBAL===\n";
75    foreach($pr as $p2) {
76        echo $p1, '::$' , $p2, "\n";
77        var_dump(property_exists($p1, $p2));
78    }
79}
80
81echo "===PROBLEMS===\n";
82try {
83    var_dump(property_exists(NULL, 'empty'));
84} catch (\TypeError $e) {
85    echo $e->getMessage() . \PHP_EOL;
86}
87try {
88    var_dump(property_exists(25,'empty'));
89} catch (\TypeError $e) {
90    echo $e->getMessage() . \PHP_EOL;
91}
92var_dump(property_exists('',''));
93var_dump(property_exists('A',''));
94var_dump(property_exists('A','123'));
95var_dump(property_exists('A','init'));
96var_dump(property_exists('A','empty'));
97var_dump(property_exists(new A, ''));
98var_dump(property_exists(new A, '123'));
99var_dump(property_exists(new A, 'init'));
100var_dump(property_exists(new A, 'empty'));
101?>
102--EXPECT--
103===A===
104obj(A)::$a
105bool(true)
106obj(A)::$b
107bool(true)
108obj(A)::$c
109bool(true)
110obj(A)::$d
111bool(false)
112obj(A)::$e
113bool(true)
114===GLOBAL===
115obj(A)::$a
116bool(true)
117obj(A)::$b
118bool(true)
119obj(A)::$c
120bool(true)
121obj(A)::$d
122bool(false)
123obj(A)::$e
124bool(true)
125===A===
126A::$a
127bool(true)
128A::$b
129bool(true)
130A::$c
131bool(true)
132A::$d
133bool(false)
134A::$e
135bool(false)
136===GLOBAL===
137A::$a
138bool(true)
139A::$b
140bool(true)
141A::$c
142bool(true)
143A::$d
144bool(false)
145A::$e
146bool(false)
147===B===
148B::$a
149bool(true)
150B::$b
151bool(true)
152B::$c
153bool(true)
154B::$d
155bool(false)
156B::$e
157bool(false)
158===GLOBAL===
159B::$a
160bool(true)
161B::$b
162bool(true)
163B::$c
164bool(true)
165B::$d
166bool(false)
167B::$e
168bool(false)
169===C===
170C::$a
171bool(true)
172C::$b
173bool(true)
174C::$c
175bool(false)
176C::$d
177bool(true)
178C::$e
179bool(false)
180===GLOBAL===
181C::$a
182bool(true)
183C::$b
184bool(true)
185C::$c
186bool(false)
187C::$d
188bool(true)
189C::$e
190bool(false)
191===C===
192obj(C)::$a
193bool(true)
194obj(C)::$b
195bool(true)
196obj(C)::$c
197bool(false)
198obj(C)::$d
199bool(true)
200obj(C)::$e
201bool(false)
202===GLOBAL===
203obj(C)::$a
204bool(true)
205obj(C)::$b
206bool(true)
207obj(C)::$c
208bool(false)
209obj(C)::$d
210bool(true)
211obj(C)::$e
212bool(false)
213===PROBLEMS===
214property_exists(): Argument #1 ($object_or_class) must be of type object|string, null given
215property_exists(): Argument #1 ($object_or_class) must be of type object|string, int given
216bool(false)
217bool(false)
218bool(false)
219bool(true)
220bool(true)
221bool(false)
222bool(false)
223bool(true)
224bool(true)
225