1--TEST-- 2Disjunctive Normal Form types in reflection 3--FILE-- 4<?php 5 6function dumpType(ReflectionType $rt, int $indent = 0) { 7 $str_indent = str_repeat(' ', 2 * $indent); 8 echo $str_indent . "Type $rt is " . $rt::class . ":\n"; 9 foreach ($rt->getTypes() as $type) { 10 if ($type instanceof ReflectionNamedType) { 11 echo $str_indent . " Name: " . $type->getName() . "\n"; 12 echo $str_indent . " String: " . (string) $type . "\n"; 13 echo $str_indent . " Allows Null: " . json_encode($type->allowsNull()) . "\n"; 14 } else { 15 dumpType($type, $indent+1); 16 } 17 } 18} 19 20function test1(): (X&Y)|(Z&Traversable)|Countable { } 21 22class Test { 23 public (X&Y)|Countable $prop; 24} 25 26dumpType((new ReflectionFunction('test1'))->getReturnType()); 27 28$rc = new ReflectionClass(Test::class); 29$rp = $rc->getProperty('prop'); 30dumpType($rp->getType()); 31 32/* Force CE resolution of the property type */ 33 34interface y {} 35class x implements Y, Countable { 36 public function count(): int { return 0; } 37} 38$test = new Test; 39$test->prop = new x; 40 41$rp = $rc->getProperty('prop'); 42dumpType($rp->getType()); 43 44?> 45--EXPECT-- 46Type (X&Y)|(Z&Traversable)|Countable is ReflectionUnionType: 47 Type X&Y is ReflectionIntersectionType: 48 Name: X 49 String: X 50 Allows Null: false 51 Name: Y 52 String: Y 53 Allows Null: false 54 Type Z&Traversable is ReflectionIntersectionType: 55 Name: Z 56 String: Z 57 Allows Null: false 58 Name: Traversable 59 String: Traversable 60 Allows Null: false 61 Name: Countable 62 String: Countable 63 Allows Null: false 64Type (X&Y)|Countable is ReflectionUnionType: 65 Type X&Y is ReflectionIntersectionType: 66 Name: X 67 String: X 68 Allows Null: false 69 Name: Y 70 String: Y 71 Allows Null: false 72 Name: Countable 73 String: Countable 74 Allows Null: false 75Type (X&Y)|Countable is ReflectionUnionType: 76 Type X&Y is ReflectionIntersectionType: 77 Name: X 78 String: X 79 Allows Null: false 80 Name: Y 81 String: Y 82 Allows Null: false 83 Name: Countable 84 String: Countable 85 Allows Null: false 86