可变长度参数列表

Version >= 5.6

PHP 5.6 引入可变长度参数列表(也称为可变参数,可变参数),使用参数名称前的 ... 令牌以指示该参数是可变参数,即,它是包括来自一个起的所有提供的参数的阵列。

function variadic_func($nonVariadic, ...$variadic) {
    echo json_encode($variadic);
}

variadic_func(1, 2, 3, 4); // prints [2,3,4]

类型名称可以添加到 ... 前面:

function foo(Bar ...$bars) {}

& 引用运算符可以在 ... 之前添加,但在类型名称之后(如果有的话)添加。考虑这个例子:

class Foo{}
function a(Foo &...$foos){
    $i = 0;
    foreach($a as &$foo){ // note the &
        $foo = $i++;
    }
}
$a = new Foo;
$c = new Foo;
$b =& $c;
a($a, $b);
var_dump($a, $b, $c);

输出:

int(0)
int(1)
int(1)

另一方面,参数数组(或 Traversable)可以解压缩,以参数列表的形式传递给函数:

var_dump(...hash_algos());

输出:

string(3) "md2"
string(3) "md4"
string(3) "md5"
...

与此片段比较而不使用 ...

var_dump(hash_algos());

输出:

array(46) {
  [0]=>
  string(3) "md2"
  [1]=>
  string(3) "md4"
  ...
}

因此,现在可以轻松地进行可变参数函数的重定向功能,例如:

public function formatQuery($query, ...$args){
    return sprintf($query, ...array_map([$mysqli, "real_escape_string"], $args));
}

除了数组之外,还可以使用 Traversables,例如 Iterator(尤其是来自 SPL 的许多子类)。例如:

$iterator = new LimitIterator(new ArrayIterator([0, 1, 2, 3, 4, 5, 6]), 2, 3);
echo bin2hex(pack("c*", ...$it)); // Output: 020304

如果迭代器无限迭代,例如:

$iterator = new InfiniteIterator(new ArrayIterator([0, 1, 2, 3, 4]));
var_dump(...$iterator);

不同版本的 PHP 表现不同:

  • 从 PHP 7.0.0 到 PHP 7.1.0(beta 1):
    • 将发生分段错误
    • PHP 进程将以代码 139 退出
  • 在 PHP 5.6 中:
    • 将显示内存耗尽的致命错误(“允许的内存大小为%d 字节耗尽”)。
    • PHP 进程将以代码 255 退出

注意:HHVM(v3.10 - v3.12)不支持解包 Traversables。此尝试中将显示警告消息仅解包容器