|
| 1 | +--TEST-- |
| 2 | +eval code: ReflectionTypes of relative class types (self, parent) from traits in classes, parameter types |
| 3 | +--FILE-- |
| 4 | +<?php |
| 5 | + |
| 6 | +$code = <<<'CODE' |
| 7 | +trait TraitExample { |
| 8 | + public function bar(parent $o) { return $o; } |
| 9 | + public function ping(self $o) { return $o; } |
| 10 | + //public function barNull(?parent $o) { return $o; } |
| 11 | + //public function pingNull(?self $o) { return $o; } |
| 12 | +} |
| 13 | +
|
| 14 | +class A { |
| 15 | +
|
| 16 | +} |
| 17 | +
|
| 18 | +class B extends A { |
| 19 | +} |
| 20 | +
|
| 21 | +class C extends B { |
| 22 | + use TraitExample; |
| 23 | +} |
| 24 | +
|
| 25 | +class D extends C {} |
| 26 | +
|
| 27 | +$instances = [ |
| 28 | + new A, |
| 29 | + new B, |
| 30 | + new C, |
| 31 | + new D, |
| 32 | +]; |
| 33 | +
|
| 34 | +foreach ($instances as $instance) { |
| 35 | + echo 'Class: ', $instance::class, PHP_EOL; |
| 36 | + $rc = new ReflectionClass($instance); |
| 37 | + $methods = $rc->getMethods(); |
| 38 | + foreach ($methods as $method) { |
| 39 | + echo "\tMethod: ", $method->name, PHP_EOL; |
| 40 | + $parameters = $method->getParameters(); |
| 41 | + foreach ($parameters as $param) { |
| 42 | + $type = $param->getType(); |
| 43 | + echo "\t\tType: ", $type, PHP_EOL; |
| 44 | + echo "\t\tInstance of: ", $type::class, PHP_EOL; |
| 45 | + $resolvedType = $type->resolveToNamedType(); |
| 46 | + echo "\t\t\tResolved Type: ", $resolvedType, PHP_EOL; |
| 47 | + echo "\t\t\tInstance of: ", $resolvedType::class, PHP_EOL; |
| 48 | +
|
| 49 | + foreach ($instances as $arg) { |
| 50 | + try { |
| 51 | + $instance->{$method->name}($arg); |
| 52 | + } catch (\TypeError $e) { |
| 53 | + echo "\t\t\t\t", $e->getMessage(), PHP_EOL; |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | +CODE; |
| 60 | + |
| 61 | +eval($code); |
| 62 | + |
| 63 | +?> |
| 64 | +--EXPECTF-- |
| 65 | +Class: A |
| 66 | +Class: B |
| 67 | +Class: C |
| 68 | + Method: bar |
| 69 | + Type: parent |
| 70 | + Instance of: ReflectionRelativeClassType |
| 71 | + Resolved Type: B |
| 72 | + Instance of: ReflectionNamedType |
| 73 | + C::bar(): Argument #1 ($o) must be of type B, A given, called in %s on line %d |
| 74 | + Method: ping |
| 75 | + Type: self |
| 76 | + Instance of: ReflectionRelativeClassType |
| 77 | + Resolved Type: C |
| 78 | + Instance of: ReflectionNamedType |
| 79 | + C::ping(): Argument #1 ($o) must be of type C, A given, called in %s on line %d |
| 80 | + C::ping(): Argument #1 ($o) must be of type C, B given, called in %s on line %d |
| 81 | +Class: D |
| 82 | + Method: bar |
| 83 | + Type: parent |
| 84 | + Instance of: ReflectionRelativeClassType |
| 85 | + Resolved Type: B |
| 86 | + Instance of: ReflectionNamedType |
| 87 | + C::bar(): Argument #1 ($o) must be of type B, A given, called in %s on line %d |
| 88 | + Method: ping |
| 89 | + Type: self |
| 90 | + Instance of: ReflectionRelativeClassType |
| 91 | + Resolved Type: C |
| 92 | + Instance of: ReflectionNamedType |
| 93 | + C::ping(): Argument #1 ($o) must be of type C, A given, called in %s on line %d |
| 94 | + C::ping(): Argument #1 ($o) must be of type C, B given, called in %s on line %d |
0 commit comments