PHP中三点(…)的含义


125

PHP中的三点(...)是什么意思?

在我的服务器中安装Magento 2时,出现错误。检查该代码,发现有一个三点(...),这会产生错误。我在下面提到了代码

return new $type(...array_values($args));

PHP 5.6中引入的数组打包/拆包
Mark Ba​​ker


4
只是一个随机注释,这是JS中的传播运算符。:)
克里斯·

@ChrisHappy在这种情况下实际上是rest运算符
肯尼·霍纳

Answers:


191

...$str被称为在PHP图示操作

此功能使您可以捕获函数的可变数量的参数,并根据需要传递传入的“普通”参数。用一个例子最容易看到:

function concatenate($transform, ...$strings) {
    $string = '';
    foreach($strings as $piece) {
        $string .= $piece;
    }
    return($transform($string));
}

echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");
// This would print:
// I'D LIKE 6 APPLES

函数声明中的参数列表中包含...运算符,它的基本含义是“ ...以及其他所有内容都应放入$ strings中”。您可以将2个或更多参数传递给此函数,第二个及后续参数将添加到$ strings数组中,可供使用。

希望这可以帮助!


1
谢谢:),为什么我应该使用SPLAT运算符,而不是我可以将数组中的所有那些字符串作为第二个参数传递?
bikash.bilz

3
@ bikash.bilz我将为回答者发言:我认为这只是语法糖。splat运算符使您免于使用[和围绕参数]。好处不多,但我认为它看起来不错。
科多斯·约翰逊

20
您也可以键入可变参数的提示。因此,在PHP 7.2上,您可以定义function myFunc($foo, string ...$bar)。然后$bar给您的函数一个字符串数组,别无其他,在运行时保证。您不能使用单个数组参数来执行此操作。
杰森

4
这不仅是语法糖,还因为它允许在上下文中使用数组,否则它们将需要固定数量的字符串。使用固定数量的字符串要求您在每次字符串数量可能更改时都重新构建源代码。
dreftymac '19

2
一个简单的例子是用于查询数据库的函数签名。function get_data($fname,$lname,$age)如果您要更改这三个字段以外的其他字段,function get_data(...$fields)则必须更改,只需在中指定所需的字段即可$fields。@heykatieben
dreftymac


13

有两种用途的省略号(...)PHP令牌他们的-think作为包装的阵列和拆包的数组。这两个目的都适用于函数参数。


当定义一个函数,如果你需要的提供给函数的变量动态数(即,你不知道有多少参数将被提供给在代码中调用时功能)使用省略号(...)令牌来将提供给该函数的所有其余参数捕获到该函数块内部可访问的数组中。省略号(...)捕获的动态参数的数量可以为零或更多。

例如

// function definition
function sum(...$numbers) { // use ellipsis token when defining function
    $acc = 0;
    foreach ($numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2, 3, 4); // provide any number of arguments

> 10

// and again...
echo sum(1, 2, 3, 4, 5);

> 15

// and again...
echo sum();

> 0

当在函数实例化中使用压缩时,省略号(...)捕获所有剩余的参数,即,您仍然可以具有任意数量的初始,固定(位置)参数:

function sum($first, $second, ...$remaining_numbers) {
    $acc = $first + $second;
    foreach ($remaining_numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2); // provide at least two arguments

> 3

// and again...
echo sum(1, 2, 3, 4); // first two are assigned to fixed arguments, the rest get "packed"

> 10

开箱

或者,在调用函数时,如果您先前向该函数提供的参数先前已合并到一个数组中,则使用省略号(...)将该数组转换为提供给该函数的各个参数-每个数组元素都分配给相应的在函数定义中命名的函数参数变量。

例如:

function add($aa, $bb, $cc) {
    return $aa + $bb + $cc;
}

$arr = [1, 2, 3];
echo add(...$arr); // use ellipsis token when calling function

> 6

$first = 1;
$arr = [2, 3];
echo add($first, ...$arr); // used with positional arguments

> 6

$first = 1;
$arr = [2, 3, 4, 5]; // array can be "oversized"
echo add($first, ...$arr); // remaining elements are ignored

> 6

使用数组函数操作数组或变量时,解包特别有用。

例如,解压缩array_slice的结果:

function echoTwo ($one, $two) {
    echo "$one\n$two";
}

$steaks = array('ribeye', 'kc strip', 't-bone', 'sirloin', 'chuck');

// array_slice returns an array, but ellipsis unpacks it into function arguments
echoTwo(...array_slice($steaks, -2)); // return last two elements in array

> sirloin
> chuck

4
这是最好的答案。非常清晰的解释和示例。谢谢!!!

解压缩对于Doctrine的OrX功能非常有用
Erdal G.

5

要使用此功能,只需警告PHP,它需要使用将该数组解压缩为变量... operator。有关更多详细信息,请参见此处,一个简单的示例如下所示:

$email[] = "Hi there";
$email[] = "Thanks for registering, hope you like it";

mail("someone@example.com", ...$email);

4

这意味着它将一个关联数组分解为一个列表。因此,您无需键入N个参数即可调用一个方法,只需调用一个即可。如果方法允许分解参数,并且参数类型相同。

对我而言,splat运算符最重要的是它可以帮助键入提示数组参数:

$items = [
    new Item(), 
    new Item()
];

$collection = new ItemCollection();
$collection->add(...$items); // !

// what works as well:
// $collection->add(new Item());
// $collection->add(new Item(), new Item(), new Item()); // :(

class Item  {};

class ItemCollection {

    /**
     * @var Item[]
     */
    protected $items = [];

    public function add(Item ...$items)
    {
        foreach ($items as &$item) {
            $this->items[] = $item;
        }
    }
} 

它节省了类型控制方面的工作,特别是在处理庞大的集合或非常面向对象的工作时。

需要注意的重要一点是,...$array尽管数组的项类型不同,但也要对其进行分解,因此您也可以采用以下丑陋的方式:

function test(string $a, int $i) {
    echo sprintf('%s way as well', $a);

    if ($i === 1) {
        echo('!');
    }
}

$params = [
    (string) 'Ugly',
    (int) 1
];

test(...$params);

// Output:
// Ugly way as well!

但是请不要。


不是那么丑。就像Doctrine的OrX函数需要一个列表一样,但是您需要传递一个数组(因为您不知道要传递多少个元素)。我发现这种方法比使用call_user_func_array更好
Erdal G.

3

这就是所谓的“ splat”运算符。基本上,那东西翻译成“任意数量的参数”。PHP 5.6引入

有关更多详细信息,请参见此处


3

似乎没有人提及它,因此请留在这里[这也将帮助Google(&Other SE)指导要求PHP中提供Rest参数的开发人员]:

如此处所示,它在JS上称为Rest Parameters,我更喜欢这种有意义的命名方式,而不是那些易碎的东西!

在PHP中,... args提供的功能称为Variadic函数,该函数是在PHP5.6上引入的。曾经使用来实现相同的功能func_get_args()

为了正确使用它,您应该在任何有助于减少样板代码的地方使用rest参数语法。


1
再加上一个帮助Google在PHP中找到Rest参数的参数
kapreski

1

我想在Magento框架中共享此运算符的用法,在该框架中它使用动态可配置参数(可想到的XML配置文件)实例化对象。

createObject从下面的代码片段中可以看到该函数,该函数接收为对象创建准备的参数数组。然后,它使用...(三个点)运算符将数组值作为真实参数传递给类的构造函数。

<?php

namespace Magento\Framework\ObjectManager\Factory;

abstract class AbstractFactory implements \Magento\Framework\ObjectManager\FactoryInterface
{
    ...

    /**
     * Create object
     *
     * @param string $type
     * @param array $args
     *
     * @return object
     * @throws RuntimeException
     */
    protected function createObject($type, $args)
    {
        try {
            return new $type(...array_values($args));
        } catch (\TypeError $exception) {
            ...
        }
    }

    ...

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.