检查可调用是否可以在 php 中接收类作为参数



我有一个可调用的$f,我想知道它是否可以接收某个类Foo的实例作为输入。

目前我正在做类似的事情

try {
$f($foo);
} catch (TypeError $e) {
throw new InvalidArgumentException('The provided function can not evaluate inputs of this type');
}

有没有办法在不实际调用可调用对象的情况下检查这一点?也许有反射或其他黑暗魔法?

如果你想能够反映任何类型的可调用对象,你需要将逻辑包装在一个小函数中。根据您是拥有数组、函数名称还是匿名函数,您需要创建ReflectionFunctionReflectionMethod。幸运的是,它们都扩展了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+,但希望这不是问题。

它目前不支持实现定义为"Foo::bar"__invoke或静态调用的对象,但如有必要,添加它们不会太难。我刚刚在 Twig 的来源中发现了非常相似的东西,它做了更彻底的工作:https://github.com/twigphp/Twig/blob/v2.8.0/src/Node/Expression/CallExpression.php#L280

你可以使用 ReflectionParameter::getType:

$f = function(Foo $foo) {};
$reflectionFunc = new ReflectionFunction($f);
$reflectionParams = $reflectionFunc->getParameters();
$reflectionType1 = $reflectionParams[0]->getType();
echo $reflectionType1;

输出:

相关内容

  • 没有找到相关文章

最新更新