检查 callable 是否可以接收 class 作为 php 中的参数
Check if callable can receive class as parameter in php
我有一个可调用的 $f
,我想知道它是否可以接收某个 class Foo
的实例作为输入。
目前我正在做类似
的事情
try {
$f($foo);
} catch (\TypeError $e) {
throw new \InvalidArgumentException('The provided function can not evaluate inputs of this type');
}
有没有办法在不实际调用可调用对象的情况下进行检查?也许用反射或其他一些黑魔法?
你可以 ReflectionParameter::getType:
$f = function(Foo $foo) {};
$reflectionFunc = new ReflectionFunction($f);
$reflectionParams = $reflectionFunc->getParameters();
$reflectionType1 = $reflectionParams[0]->getType();
echo $reflectionType1;
输出:
Foo
如果您希望能够反映任何类型的可调用对象,您需要将逻辑封装在一个小函数中。根据您是否有数组、函数名或匿名函数,您需要创建一个 ReflectionFunction
or ReflectionMethod
. Fortunately, these both extend ReflectionFunctionAbstract
,以便我们可以类型提示 return 值。
function reflectCallable($arg): ReflectionFunctionAbstract {
if (is_array($arg)) {
$ref = new ReflectionMethod(...$arg);
} elseif (is_callable($arg)) {
$ref = new ReflectionFunction($arg);
}
return $ref;
}
这将为您 return 为您的可调用值提供合适的对象,然后您可以使用它来获取参数并采取相应的行动:
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;
}
}
请注意,这不会执行任何错误处理 - 如果可调用对象不采用任何参数或第一个参数没有类型,您可能会得到 warnings/notices。它还需要 PHP 7+,但希望这不是问题。
目前不支持实现 __invoke
的对象或定义为 "Foo::bar"
的静态调用,但如果需要的话添加它们并不难。 我刚刚在 Twig 的源代码中发现了一些非常相似的东西,它做得更彻底:https://github.com/twigphp/Twig/blob/v2.8.0/src/Node/Expression/CallExpression.php#L280
我有一个可调用的 $f
,我想知道它是否可以接收某个 class Foo
的实例作为输入。
目前我正在做类似
的事情try {
$f($foo);
} catch (\TypeError $e) {
throw new \InvalidArgumentException('The provided function can not evaluate inputs of this type');
}
有没有办法在不实际调用可调用对象的情况下进行检查?也许用反射或其他一些黑魔法?
你可以 ReflectionParameter::getType:
$f = function(Foo $foo) {};
$reflectionFunc = new ReflectionFunction($f);
$reflectionParams = $reflectionFunc->getParameters();
$reflectionType1 = $reflectionParams[0]->getType();
echo $reflectionType1;
输出:
Foo
如果您希望能够反映任何类型的可调用对象,您需要将逻辑封装在一个小函数中。根据您是否有数组、函数名或匿名函数,您需要创建一个 ReflectionFunction
or ReflectionMethod
. Fortunately, these both extend ReflectionFunctionAbstract
,以便我们可以类型提示 return 值。
function reflectCallable($arg): ReflectionFunctionAbstract {
if (is_array($arg)) {
$ref = new ReflectionMethod(...$arg);
} elseif (is_callable($arg)) {
$ref = new ReflectionFunction($arg);
}
return $ref;
}
这将为您 return 为您的可调用值提供合适的对象,然后您可以使用它来获取参数并采取相应的行动:
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;
}
}
请注意,这不会执行任何错误处理 - 如果可调用对象不采用任何参数或第一个参数没有类型,您可能会得到 warnings/notices。它还需要 PHP 7+,但希望这不是问题。
目前不支持实现 我刚刚在 Twig 的源代码中发现了一些非常相似的东西,它做得更彻底:https://github.com/twigphp/Twig/blob/v2.8.0/src/Node/Expression/CallExpression.php#L280__invoke
的对象或定义为 "Foo::bar"
的静态调用,但如果需要的话添加它们并不难。