检查callable是否可以在php中接收类作为参数 [英] Check if callable can receive class as parameter in php

查看:32
本文介绍了检查callable是否可以在php中接收类作为参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a callable $f and I would like to know if it can receive an instance of a certain class Foo as input.

目前我正在做类似的事情

At the moment I'm doing something like

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

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

Is there a way to check this WITHOUT actually invoking the callable? Maybe with reflection or some other dark magic?

推荐答案

如果您希望能够反映任何类型的可调用对象,您需要将逻辑封装在一个小函数中.根据您是否有数组、函数名或匿名函数,您需要创建一个 ReflectionFunction反射方法.幸运的是,这些都扩展了 ReflectionFunctionAbstract,所以我们可以对返回值进行类型提示.

If you want to be able to reflect any kind of callable, you'll need to wrap up the logic in a small function. Depending on whether you've got an array, a function name or an anonymous function, you need to create either a ReflectionFunction or ReflectionMethod. Fortunately, these both extend ReflectionFunctionAbstract, so we can type-hint the return value.

function reflectCallable($arg): ReflectionFunctionAbstract {
    if (is_array($arg)) {
        $ref = new ReflectionMethod(...$arg);
    } elseif (is_callable($arg)) {
        $ref = new ReflectionFunction($arg);
    }

    return $ref;
}

这将为您的可调用值返回适当的对象,然后您可以使用它来获取参数并采取相应的行动:

This will return you the appropriate object for your callable value, which you can then use to fetch the parameters and act accordingly:

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/c5vM

请注意,这不会进行任何错误处理 - 如果可调用对象不带任何参数或第一个参数没有类型,您可能会收到警告/通知.它还需要 PHP 7+,但希望这不是问题.

Note that this doesn't do any error handling - you'll probably get warnings/notices if the callable doesn't take any parameters or the first parameter doesn't have a type. It also requires PHP 7+, but hopefully that's not an issue.

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

It doesn't currently support objects that implement __invoke or static calls defined as "Foo::bar", but they wouldn't be too hard to add if necessary. I've just found something very similar in the source of Twig, which does a more thorough job: https://github.com/twigphp/Twig/blob/v2.8.0/src/Node/Expression/CallExpression.php#L280

这篇关于检查callable是否可以在php中接收类作为参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆