PHP中三点(...)的含义

abu*_*abu 90 php

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

当我在我的Sever中安装Magento 2时出现错误.调查代码,发现有一个三点(...),产生错误.我提到了下面的代码

return new $type(...array_values($args));
Run Code Online (Sandbox Code Playgroud)

Sau*_*ogi 146

...$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
Run Code Online (Sandbox Code Playgroud)

函数声明中的参数列表中包含...运算符,它基本上意味着"......其他所有内容都应该进入$ strings".您可以将2个或更多参数传递给此函数,第二个和后续参数将添加到$ strings数组中,随时可以使用.

希望这可以帮助!

  • 您也可以键入提示可变参数.所以在PHP 7.2上,你可以定义`function myFunc($ foo,string ... $ bar)`.然后`$ bar`为你的函数提供一个字符串数组,没有别的,在运行时保证.您不能使用单个数组参数执行此操作. (7认同)
  • 这不仅仅是语法糖,因为它允许在上下文中使用数组,否则需要固定数量的字符串。使用固定数量的字符串需要您在每次字符串数量可能发生变化时重构源代码。 (5认同)
  • 一个简单的例子是用于查询数据库的函数签名。如果您想要除这三个之外的字段,则必须更改“function get_data($fname,$lname,$age)”,而不必更改“function get_data(...$fields)”,您只需指定您想要的字段想要在“$fields”中。@heykatieben (4认同)
  • 谢谢:),为什么我应该使用 SPLAT 运算符,而不是这个,我可以将数组中的所有这些字符串作为第二个参数传递??? (3认同)
  • @ bikash.bilz我将为回答者发言:我认为这只是[语法糖](https://en.wikipedia.org/wiki/Syntactic_sugar)。splat运算符使您免于用`[`和`]`包围参数。好处不多,但我认为它看起来不错。 (2认同)
  • @dreftymac 这与仅将 `function get_data($fields)` 作为数组执行有什么不同?它很适合打字,也很方便,但如果您实际上有一个函数需要一定数量的命名参数,您不应该将其更改为可变参数,这样就可以避免重构。如果您有一个必需的新字段,那么它确实需要重构。在您的示例中,调用者是否应该以某种方式知道第一个参数是 fname,第二个参数是 lname? (2认同)
  • @Guybrush 我将“你不应该”或“你应该”留给与相关团队成员进行[代码审查](https://codereview.stackexchange.com)讨论时间。语言功能已经存在,并且有很多理由使用(或不使用)它。对于SO,向不理解的人解释事情就足够了,让他们自己处理“应该”的事情。 (2认同)

blo*_*les 36

有两种用途的省略号(...)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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

打开包装

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

例如:

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
Run Code Online (Sandbox Code Playgroud)

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

例如,解包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
Run Code Online (Sandbox Code Playgroud)


rap*_*2-h 18

每个答案都指同一篇博文,除此之外,这里是关于可变长度参数列表的官方文档:

http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list

在PHP 5.6及更高版本中,参数列表可能包含...标记,表示该函数接受可变数量的参数.参数将作为数组传递给给定变量

看来"splat"操作符不是官方名称,仍然很可爱!


yer*_*rgo 17

意思是它将关联数组分解为列表。因此,您不需要键入 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;
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

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

需要注意的是,...$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!
Run Code Online (Sandbox Code Playgroud)

但请不要。


PHP 8 更新 - 命名参数

从 PHP 8 开始,您现在可以分解关联数组,即具有键值的数组。如果您在具有相同名称的参数的函数中使用它,PHP 会将值传输到适当的变量:

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!
Run Code Online (Sandbox Code Playgroud)

并且您可以稍微不用担心参数的顺序。


PHP 8.1 更新 - 创建可调用的新语法

尽管使用了数组,但...还是获得了一个全新的、非常有用的功能,可以帮助从任何上下文创建可调用对象:

$f = strtoupper(...); // creating a callable
echo $f('fo');

class test {
    public function func($a) {
        echo $a . PHP_EOL;
    }
}

$f = (new test)
         ->func(...); // creating a callable

$f('x');
Run Code Online (Sandbox Code Playgroud)


jaw*_*ira 15

PHP 8.1中,这种语法“ (...)”被用作创建可调用对象的新方法。

PHP 8.1 之前:

$callable = [$this, 'myMethod'];
Run Code Online (Sandbox Code Playgroud)

PHP 8.1 之后:

$callable = $this->myMethod(...);
Run Code Online (Sandbox Code Playgroud)

来源: https: //wiki.php.net/rfc/first_class_callable_syntax

  • 这不是作者最初问题的答案,但它可能与任何搜索“php 3dots”的人相关 (8认同)

Lea*_*per 6

To use this feature, just warn PHP that it needs to unpack the array into variables using the ... operator. See here for more details, a simple example could look like this:

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

mail("someone@example.com", ...$email);
Run Code Online (Sandbox Code Playgroud)


jaw*_*ira 6

In PHP 7.4 the ellipsis is also the Spread operator:

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
Run Code Online (Sandbox Code Playgroud)

Source: https://wiki.php.net/rfc/spread_operator_for_array