通过 call_user_func_array 将命名参数传递给 php 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6610556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:50:40  来源:igfitidea点击:

Passing named parameters to a php function through call_user_func_array

phpfunction

提问by Wagemage

When trying to call a function in a child class with an arbitrary set of parameters, I'm having the following problem:

当尝试使用一组任意参数调用子类中的函数时,我遇到了以下问题:

class Base{

    function callDerived($method,$params){
        call_user_func_array(array($this,$method),$params);
    }
}

class Derived extends Base{
    function test($foo,$bar){
        print "foo=$foo, bar=$bar\n";
    }
}

$d = new Derived();
$d->callDerived('test',array('bar'=>'2','foo'=>1));

Outputs:

输出:

foo=2, bar=1

Which... is not exactly what I wanted - is there a way to achieve this beyondre-composing the array with the index order of func_get_args? And yes, of course, I could simply pass the whole array and deal with it in the function... but that's not what I want to do.

哪个......不完全是我想要的 -除了使用func_get_args的索引顺序重新组合数组之外,有没有办法实现这一点?是的,当然,我可以简单地传递整个数组并在函数中处理它……但这不是我想要做的。

Thanks

谢谢

回答by deceze

No. PHP does not support named parameters. Only the order of parameters is taken into account. You could probably take the code itself apart using the ReflectionClassto inspect the function parameter names, but in the end you'd need to use this to reorder the array anyway.

不。PHP 不支持命名参数。只考虑参数的顺序。您可能可以使用ReflectionClass将代码本身分开来检查函数参数名称,但最终您还是需要使用它来重新排序数组。

回答by Gábor G.

The stock PHP class ReflectionMethodis your friend.

股票 PHP 类ReflectionMethod是您的朋友。

Example:

例子:

class MyClass { 
    function myFunc($param1, $param2, $param3='myDefault') { 
        print "test"; 
    } 
}

$refm = new ReflectionMethod('MyClass', 'myFunc');

foreach ($refm->getParameters() as $p) 
    print "$p\n";

And the result:

结果:

Parameter #0 [ <required> $param1 ]
Parameter #1 [ <required> $param2 ]
Parameter #2 [ <optional> $param3 = 'myDefault' ]

At this point you know the names of the parameters of the target function. With this information you can modify your method 'callDerived', and you can re-order the array to call_user_func_arrayaccording to the parameter names.

此时你就知道了目标函数的参数名称。有了这些信息,您可以修改您的方法“ callDerived”,并且您可以根据参数名称将数组重新排序为call_user_func_array

回答by Vince

Good news, I had the same concern (I was looking for named arguments in PHP, like Python does), and found this useful tool : https://github.com/PHP-DI/Invoker

好消息,我也有同样的担忧(我在 PHP 中寻找命名参数,就像 Python 一样),并找到了这个有用的工具:https: //github.com/PHP-DI/Invoker

This uses the reflection API to feed a callable with some arguments from an array and also use optional arguments defaults for other parameters that are not defined in the array.

这使用反射 API 为可调用对象提供数组中的一些参数,并且还为未在数组中定义的其他参数使用可选参数默认值。

$invoker = new Invoker\Invoker;
$result = $invoker->call(array($object, 'method'), array(
    "strName"  => "Lorem",
    "strValue" => "ipsum",
    "readOnly" => true,
    "size"     => 55,
));

Have fun

玩得开心

回答by iautomation

You can simply pass an array and extract:

您可以简单地传递一个数组并提取:

function add($arr){
    extract($arr, EXTR_REFS);
    return $one+$two;
}
$one = 1;
$two = 2;
echo add(compact('one', 'two')); // 3

This will extract as references, so there is close to no overhead.

这将提取为引用,因此几乎没有开销。

回答by Franz Fankhauser

I use a bitmask instead of boolean parameters:

我使用位掩码而不是布尔参数:

// Ingredients
define ('TOMATO',    0b0000001);
define ('CHEESE',    0b0000010);
define ('OREGANO',   0b0000100);
define ('MUSHROOMS', 0b0001000);
define ('SALAMI',    0b0010000);
define ('PEPERONI',  0b0100000);
define ('ONIONS',    0b1000000);

function pizza ($ingredients) {
  $serving = 'Pizza with';
  $serving .= ($ingredients&TOMATO)?' Tomato':''; 
  $serving .= ($ingredients&CHEESE)?' Cheese':''; 
  $serving .= ($ingredients&OREGANO)?' Oregano':''; 
  $serving .= ($ingredients&MUSHROOMS)?' Mushrooms':''; 
  $serving .= ($ingredients&SALAMI)?' Salami':''; 
  $serving .= ($ingredients&ONIONS)?' Onions':''; 
  return trim($serving)."\n" ;
}

// Now order your pizzas!
echo pizza(TOMATO | CHEESE | SALAMI); 
echo pizza(ONIONS | TOMATO | MUSHROOMS | CHEESE); // "Params" are not positional

回答by kovalenko-alex

For those who still might stumble on the question (like I did), here is my approach:

对于那些仍然可能会偶然发现这个问题的人(就像我一样),这是我的方法:

since PHP 5.6you can use ...as mentioned here:

因为PHP 5.6,你可以使用...提到这里

In this case you could use something like this:

在这种情况下,你可以使用这样的东西:

class Base{

    function callDerived($method,...$params){
            call_user_func_array(array($this,$method),$params);
        }
}

class Derived extends Base{
    function test(...$params){
        foreach ($params as $arr) {
            extract($arr);
        }
        print "foo=$foo, bar=$bar\n";
    }
}

$d = new Derived();
$d->callDerived('test',array('bar'=>'2'),array('foo'=>1)); 

//print: foo=1, bar=2

回答by Erick

There is a way to do it and is using arrays (the most easy way):

有一种方法可以使用数组(最简单的方法):

class Test{
    public $a  = false;
    private $b = false;
    public $c  = false;
    public $d  = false;
    public $e  = false;
    public function _factory(){
        $args    = func_get_args();
        $args    = $args[0];
        $this->a = array_key_exists("a",$args) ? $args["a"] : 0;
        $this->b = array_key_exists("b",$args) ? $args["b"] : 0;
        $this->c = array_key_exists("c",$args) ? $args["c"] : 0;
        $this->d = array_key_exists("d",$args) ? $args["d"] : 0;
        $this->e = array_key_exists("e",$args) ? $args["e"] : 0;
    }
    public function show(){
        var_dump($this);
    }
}

$test = new Test();
$args["c"]=999;
$test->_factory($args);
$test->show();

a full explanation can be found in my blog: http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php/

完整的解释可以在我的博客中找到:http: //www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php/