在PHP中匹配关联数组和函数调用中的函数参数

在PHP中匹配关联数组和函数调用中的函数参数,php,function,reflection,Php,Function,Reflection,我有一个如下形式的关联数组: $params = array( 'paramName_4'=>'param_4', 'paramName_2'=>'param_2', // ..., 'paramName_6'=>'param_6', ); 我还有一个函数myFunction定义为: public function myFunction($paramName_1, $paramName_2, $paramName_3, ....); PH

我有一个如下形式的关联数组:

$params = array(
    'paramName_4'=>'param_4', 
    'paramName_2'=>'param_2',
    // ...,
    'paramName_6'=>'param_6',
); 
我还有一个函数
myFunction
定义为:

public function myFunction($paramName_1, $paramName_2, $paramName_3, ....);
PHP中是否存在“解析”函数,以便我可以通过匹配参数调用函数
myFunction
(即使它们没有按照
myFunction
的参数序列排序)?换句话说,我能做什么

my_magic(__NAMESPACE__.'\\myFunction', $params);

这个“神奇”的功能真的存在吗?如果没有,我如何实现它?

您可以使用。以下是方法:

// The input is the array of arguments and the function name
$arguments = array(....);
$functionName = __NAMESPACE__.'\\myFunction';

$reflector = new \ReflectionFunction($functioName);
$params = $reflector->getParameters();
$values = array();

foreach ($params as $param) {
    $name = $param->getName();
    $isArgumentGiven = array_key_exists($name, $arguments);
    if (!$isArgumentGiven && !$param->isDefaultValueAvailable() {
        die ("Parameter $name is mandatory but was not provided");
    }

    $values[$param->getPosition()] =
        $isArgumentGiven ? $arguments[$name] : $param->getDefaultValue();
}

// You can now call the function:
call_user_func($functionName, $values);

您可以使用。以下是方法:

// The input is the array of arguments and the function name
$arguments = array(....);
$functionName = __NAMESPACE__.'\\myFunction';

$reflector = new \ReflectionFunction($functioName);
$params = $reflector->getParameters();
$values = array();

foreach ($params as $param) {
    $name = $param->getName();
    $isArgumentGiven = array_key_exists($name, $arguments);
    if (!$isArgumentGiven && !$param->isDefaultValueAvailable() {
        die ("Parameter $name is mandatory but was not provided");
    }

    $values[$param->getPosition()] =
        $isArgumentGiven ? $arguments[$name] : $param->getDefaultValue();
}

// You can now call the function:
call_user_func($functionName, $values);

是的,您可以按照@Jon的示例使用反射,但是如果问题只是参数的顺序不正确,为什么不使用
ksort()
uksort()
将它们按正确的顺序排列呢

然后可以使用
调用用户函数数组()。问题解决了

$params = array(....);

uksort($params, function($a,$b) {
    //sort the params into the known order....
    $sortOrder = array('param1','param2','param3','param4');
    return (array_search($a, $sortOrder) > array_search($b, $sortOrder)) ? -1 : 1;
});

//now that $params is in the right order we can do this....
$retVal = call_user_func_array($func, $params);

我在这里硬编码了参数顺序,因为这是最有效的方法。如果调用的函数事先不知道正确的参数顺序,则需要使用反射。但我认为这是不太可能的(将未知参数列表传递到未知函数听起来像是黑客的金矿)

是的,您可以按照@Jon的示例使用反射,但如果问题只是参数顺序不正确,为什么不直接使用
ksort()
uksort()
将它们按正确的顺序排列

然后可以使用
调用用户函数数组()。问题解决了

$params = array(....);

uksort($params, function($a,$b) {
    //sort the params into the known order....
    $sortOrder = array('param1','param2','param3','param4');
    return (array_search($a, $sortOrder) > array_search($b, $sortOrder)) ? -1 : 1;
});

//now that $params is in the right order we can do this....
$retVal = call_user_func_array($func, $params);


我在这里硬编码了参数顺序,因为这是最有效的方法。如果调用的函数事先不知道正确的参数顺序,则需要使用反射。但我认为这是不太可能的(将未知参数列表传递到未知函数听起来像是黑客的金矿)

这是一个为给定函数/方法执行参数解析的库:。

这是一个为给定函数/方法执行参数解析的库:。

避免此类函数调用是有效的还是更可取?@JeanValjean:效率很低,所以不要在循环中执行。但如果少用的话,它会是一个极大的方便。这段代码是根据我自己的一个函数改编的,因此我当然觉得它很有用。+1,但我认为我应该将参数按正确的顺序排序;反射似乎有些过分。@Jon为了提高性能,我应该提供一个类的编译版本,但对于这样一个罕见的调用来说,工作量太大:)它是有效的还是最好避免这种函数调用?@JeanValjean:效率很低,所以不要在循环中进行。但如果少用的话,它会是一个极大的方便。这段代码是根据我自己的一个函数改编的,因此我当然觉得它很有用。+1,但我认为我应该将参数按正确的顺序排序;反射似乎有些过分。@Jon为了提高性能,我应该提供类的编译版本,但对于这样一个罕见的调用,这项工作太多了:),因为只有当参数的名称与它们在函数签名中出现的顺序相同时,这项工作才会起作用。没有真正的函数具有名为
param1
param2
@Jon的参数-这就是为什么您可能会使用
uksort()
。只需编写一个小的排序函数,将参数按您期望的顺序进行排序;它可以是你喜欢的任何顺序。但是你不知道正确的顺序是什么,或者你不想硬编码它。这就是你必须反思的原因。是的。。。如果您不知道顺序是什么,那么是的,您必须使用反射。但真的吗?获取一个参数列表,可能直接来自用户输入(
$\u POST
?),并将它们传递到我们事先不知道的函数中??这听起来像是黑客的梦想。@SDC我的问题是供内部使用的,不是为了匹配HTTP请求中的参数!我相信我所问的是许多web应用程序框架所做的事情(例如,Symfony用于到控制器的路由匹配),因为只有当参数的名称与它们在函数签名中出现的顺序相同时,这才起作用。没有真正的函数具有名为
param1
param2
@Jon的参数-这就是为什么您可能会使用
uksort()
。只需编写一个小的排序函数,将参数按您期望的顺序进行排序;它可以是你喜欢的任何顺序。但是你不知道正确的顺序是什么,或者你不想硬编码它。这就是你必须反思的原因。是的。。。如果您不知道顺序是什么,那么是的,您必须使用反射。但真的吗?获取一个参数列表,可能直接来自用户输入(
$\u POST
?),并将它们传递到我们事先不知道的函数中??这听起来像是黑客的梦想。@SDC我的问题是供内部使用的,不是为了匹配HTTP请求中的参数!我相信我所问的是许多web应用程序框架的功能(例如,Symfony用于控制器匹配的路由)