2012-12-20 23 views
4

可能重複時:
PHP Reflection - Get Method Parameter Type As String類型提示在PHP調用任意函數(封閉件)

捷希凱PHP microframework確實基於自動類型提示回調注射。例如,在Silex中,可以使用任意參數提供Closure參數,如下所示:

$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); 
    
+3

他們將使用[思考](http://php.net/manual/en/ book.reflection.php)。閉包在內部轉換爲[Closure](http://php.net/manual/en/class.closure.php)類的實例,反射對其就像任何其他對象一樣工作。你應該能夠通過檢查對象的__invoke()方法來獲得閉包的參數列表。 – DaveRandom

回答

3

事實上,他們正在使用Reflection,具體如下:

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()); 

我的計算器中發現的另一個問題可能是一個更好的回答你的問題。

如果你讓我來簡化包括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);