Deducing PHP Closure parameters

2019-04-24 11:51发布

问题:

Is there any chance that I can deduce PHP Closure parameters type information? Consider this example:

<?php

$foo = function(array $args)
{
    echo $args['a'] . ' ' . $args['b'];
};

$bar = function($a, $b)
{
    echo $a . ' ' . $b;
};

$closure = /* some condition */ $foo : $bar;

if(/* $closure accepts array? */)
{
    call_user_func($closure, ['a' => 5, 'b' => 10]);
}
else
{
    call_user_func($closure, 5, 10);
}

?>

I want to leave some freedom for user so he or she could decide which way is better to define a Closure that will be registered in my dispatcher - will it accept parameters in associative array or directly as Closure parameters. So, dispatcher need to deduce parameters of the passed Closure to determine which way should it call this Closure. Any ideas?

回答1:

Use reflection, if you need to make decisions, based on code structure. In your case ReflectionFunction and ReflectionParameter are your friends.

<?php
header('Content-Type: text/plain; charset=utf-8');

$func = function($a, $b){ echo implode(' ', func_get_args()); };

$closure    = $func;
$reflection = new ReflectionFunction($closure);
$arguments  = $reflection->getParameters();

if($arguments && $arguments[0]->isArray()){
    echo 'Giving array. Result: ';
    call_user_func($closure, ['a' => 5, 'b' => 10]);
} else {
    echo 'Giving individuals. Result: ';
    call_user_func($closure, 5, 10);
}
?>

Output:

Giving individuals. Result: 5 10

Change definition to test:

$func = function(array $a){ echo implode(' ', $a); };

Output:

Giving array. Result: 5 10


回答2:

It would be much easier to have your function be able to accept different types of input.

For instance, in this case:

$foo = function() {
    $args = func_get_args();
    if( is_array($args[0])) $args = $args[0];
    echo $args[0]." ".$args[1];
}


标签: php closures