在PHP中,将一个数组作为参数传递,而不是一个数组。

172

我记得在PHP中有一种方法可以将数组作为函数的参数列表传递,将数组解除引用成为标准的func($arg1, $arg2)方式。但现在我不知道该怎么做了。我记得通过引用传递的方式,如何“全局”传递参数...但不知道如何将数组解除列表成为参数。

可能只需要像func(&$myArgs)这样简单,但我很确定那不是正确的方法。但是,遗憾的是,php.net手册到目前为止还没有透露任何信息。虽然我过去一年左右没有使用过这个特定的功能。

4个回答

197

正如已经提到的那样, 在 PHP 5.6+ 中,您可以(应该!)使用 ... 标记(又称“扩展运算符”,是 变长函数 功能的一部分)来轻松调用带有参数数组的函数:

function variadic($arg1, $arg2)
{
    // Do stuff
    echo $arg1.' '.$arg2;
}

$array = ['Hello', 'World'];

// 'Splat' the $array in the function call
variadic(...$array);

// => 'Hello World'

注意:索引数组项按照在数组中的位置而非键来映射到参数。 自PHP8以来,并且感谢命名参数,可以使用关联数组的命名键进行展开:
$array = [
    'arg2' => 'Hello',
    'arg1' => 'World'
];

variadic(...$array);

// => 'World Hello'

(感谢mickmackusa提供此注释!)

根据CarlosCarucce的评论,这种参数解包形式在所有情况下都是最快的方法。在某些比较中,它比call_user_func_array快5倍以上。

附言

因为我认为这非常有用(虽然与问题没有直接关系):您可以在函数定义中类型提示splat运算符参数,以确保所有传递的值都匹配特定类型。

(只需记住,这样做必须是您定义的最后一个参数,并且它将所有传递给函数的参数捆绑到数组中。)

这非常适合确保数组包含特定类型的项目:

// Define the function...
function variadic($var, SomeClass ...$items)
{
    // $items will be an array of objects of type `SomeClass`
}

// Then you can call...
variadic('Hello', new SomeClass, new SomeClass);
    
// or even splat both ways
$items = [
    new SomeClass,
    new SomeClass,
];

variadic('Hello', ...$items);

7
与使用call_user_func_array相比,这种方法在性能上有很大的提升。因此,如果你使用的是php 5.6+的版本,我建议你使用这种方法。这里有一个测试,该测试被引用在官方php维基中。 - CarlosCarucce
1
一个相关的附注:命名参数可以被解包并且会保留它们的键(而不是元素的位置)。PHP是否允许使用命名参数以便在函数调用时省略可选参数? (请查看答案末尾的展开技术) - mickmackusa
以防你像我一样错过了,因为我喜欢快速浏览,这里的关键是调用中数组前面的"..."。 - Maciek Semik

188

52
“Argument unpacking”(参数展开)是PHP 5.6新增的功能(https://wiki.php.net/rfc/argument_unpacking)。它使用“splat operator”(展开运算符):“...”。它的语法如下:$args = [1,2,3]; function(...$args){} - arothuis
4
如果您希望调用的函数是对象上的实例方法,而不是全局空间中的函数名称,该怎么办? - ahnbizcad
6
如果您想要使用一个对象的方法,就需要使用一个“callable”函数,这个函数会使用call_user_func_array,只不过第一个参数是一个数组,其中第一个元素是对象,第二个元素是方法名。例如:call_user_func_array([$object, 'method'], $myArgs); - SteveB
这个答案不错,但已经过时了。请查看simonhamp的更简单的现代PHP解决方案。 - Joseph Meadows

85

还要注意,如果您想将实例方法应用于数组,需要将函数传递为:

call_user_func_array(array($instance, "MethodName"), $myArgs);

4
@understackеңЁй“ҫжҺҘйЎөйқўдёҠжҸҗдҫӣзҡ„$foo->bar()зӨәдҫӢе»әи®®дҪҝз”Ёarray($instance, "MethodName")гҖӮ - Paul Calcraft
12
太棒了,我用这个方法避免在子类中重复构造函数参数 :) call_user_func_array(array(parent, "__construct"), func_get_args()); - Jason

11

为了完整起见,从PHP 5.1开始这也可以工作:

<?php
function title($title, $name) {
    return sprintf("%s. %s\r\n", $title, $name);
}
$function = new ReflectionFunction('title');
$myArray = array('Dr', 'Phil');
echo $function->invokeArgs($myArray);  // prints "Dr. Phil"
?>

查看:http://php.net/reflectionfunction.invokeargs

对于您使用的方法,请改用ReflectionMethod::invokeArgs,并将对象作为第一个参数传递。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接