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