【问题标题】:Type hinting when calling arbitrary functions (closures) in PHP在 PHP 中调用任意函数(闭包)时的类型提示
【发布时间】:2012-12-07 17:26:12
【问题描述】:

Silex PHP 微框架基于自动类型提示进行回调注入。例如,在 Silex 中,可以提供带有任意参数的闭包参数,如下所示:

$app->get('/blog/show/{postId}/{commentId}', function ($commentId, $postId) {
    //...
});
$app->get('/blog/show/{id}', function (Application $app, Request $request, $id) {
    //...
});
// following works just as well - order of arguments is not important
$app->get('/blog/show/{id}', function (Request $request, Application $app, $id) {
    //...
});

我该怎么做?我对将参数类型作为字符串获取不感兴趣。我正在寻找一种“无条件”的全自动解决方案。换句话说,

  1. 对于一些可能的参数:

    $possible_arguments = [
        new Class_A(), 
        new Class_B(), 
        new Class_C(), 
        new Another_Class, 
        $some_class
    ];
    
  2. 对于具有任意数量的任意参数的闭包,它只能包含上面定义的那些参数:

    $closure = function (Class_B $b, Another_Class, $a) {
        // Do something with $a and $b
    };
    
  3. 我只需要获取匹配的参数才能使用它们调用闭包:

    // $arguments is now [$possible_arguments[1], $possible_arguments[3]]
    call_user_func_array($closure, $arguments);
    

【问题讨论】:

  • 他们将使用Reflection。闭包在内部被转换为 Closure 类的实例,反射在其上工作就像任何其他对象一样。您应该能够通过检查对象的 __invoke() 方法来获取闭包的参数列表。

标签: php closures


【解决方案1】:

他们确实在使用Reflection,特别是在the ControllerResolver class

如果您让我简化为仅包含Closure 的一种情况并且仅包含对象类型参数:

$availableArguments = array($a, new B(), $c);
$arguments = array();
$reflection = new \ReflectionFunction($callback);  // $callback is a Closure
foreach ($reflection->getParameters() as $param) {
    if ($paramClass = $param->getClass()) {
        foreach ($availableArguments as $proposedArgument) {
            if ($paramClass->isInstance($proposedArgument)) {
                $arguments[] = $proposedArgument;
                break;
            }
        }
    }
}
call_user_func_array($callback, $arguments);

【讨论】:

    【解决方案2】:

    我的猜测是使用反射。

    http://php.net/manual/en/class.reflectionparameter.php

    超级简单的例子:

    function pre($var)
    {
        echo '<pre>' . var_export($var, true) . '</pre>';
    }
    
    interface TestInterface
    {
    }
    
    class TestClass
    {
        public function __construct(TestInterface $testArg)
        {
        }
    }
    
    function TestFunc(TestInterface $testArg)
    {
    }
    
    // for a class...
    
    $className = 'TestClass';
    $methodName = '__construct';
    
    $argNumber = 0;
    
    $ref = new ReflectionParameter([$className, $methodName], $argNumber);
    
    pre($ref);
    pre($ref->getClass());
    
    
    
    // for a function...
    $funcName = 'TestFunc';
    $argNumber = 0;
    
    $ref = new ReflectionParameter($funcName, $argNumber);
    
    pre($ref);
    pre($ref->getClass());
    

    我在 stackoverflow 上发现的另一个问题可能是您问题的更好答案:PHP Reflection - Get Method Parameter Type As String

    【讨论】:

      猜你喜欢
      • 2020-06-18
      • 1970-01-01
      • 2019-11-10
      • 2013-01-29
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 2018-10-28
      • 2014-03-06
      相关资源
      最近更新 更多