Если вы хотите, чтобы можно было отразить любой вызываемый тип, вам нужно заключить логику в небольшую функцию. В зависимости от того, есть ли у вас массив, имя функции или анонимная функция, вам нужно создать либо ReflectionFunction
, либо ReflectionMethod
. К счастью, они оба расширяют ReflectionFunctionAbstract
, поэтому мы можем напечатать возвращаемое значение.
function reflectCallable($arg): ReflectionFunctionAbstract {
if (is_array($arg)) {
$ref = new ReflectionMethod(...$arg);
} elseif (is_callable($arg)) {
$ref = new ReflectionFunction($arg);
}
return $ref;
}
Это вернет вам соответствующий объект для вашего вызываемого значения, который вы затем сможете использовать для получения параметров и действовать соответственно:
function definedFunc(Foo $foo) {}
$callable = function(Foo $foo) {};
class Bar { public function baz(Foo $foo) {} }
foreach (['definedFunc', $callable, ['Bar', 'baz']] as $callable) {
$reflected = reflectCallable($callable);
if ((string) $reflected->getParameters()[0]->getType() === 'Foo') {
echo 'Callable takes Foo', PHP_EOL;
}
}
См. https://3v4l.org/c5vmM
Обратите внимание, что это не делает никакой обработки ошибок - вы, вероятно, получите предупреждения / уведомления, если вызываемый объект не принимает никаких параметров или первый параметр не имеет типа. Также требуется PHP 7+, но, надеюсь, это не проблема.
В настоящее время он не поддерживает объекты, которые реализуют __invoke
или статические вызовы, определенные как "Foo::bar"
, но добавить их при необходимости не составит труда. Я только что нашел что-то очень похоже на источник Twig, который делает более тщательную работу: https://github.com/twigphp/Twig/blob/2.x/lib/Twig/Node/Expression/Call.php#L262