如何让 PHP 理解函数参数的数组或 splat 运算符(3 个点...)?

6 php function splat

我有这个代码:

function test(...$strings)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

它允许我像这样调用 test() :

test('a', 'series of', 'strings go here');
Run Code Online (Sandbox Code Playgroud)

这有效。然而,我经常想做:

test([ 'a', 'series of', 'strings go here' ]);
Run Code Online (Sandbox Code Playgroud)

或者:

test($an_array_of_strings);
Run Code Online (Sandbox Code Playgroud)

事实上,我非常确定这有效,以至于当我开始收到有关“数组到字符串转换”的错误时,我感到震惊和困惑。

我的意思是,“...”语法是一种特殊的语言构造,专门用于将函数的可变数量的参数转换为数组!我什至不明白为什么它不会自动理解这种非常常见/有用的做法。

既然它(显然)没有,是否有某种方法可以完成此任务而不必使用两个单独的函数?我不想要一个单独的:

function test_array($strings = [])
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

Ama*_*dan 7

反过来也是一样的:

test(...$an_array_of_strings);
Run Code Online (Sandbox Code Playgroud)

如果你想让它自动化(这样你就不必使用...将数组放到参数上),你需要手动测试是否$strings只有一个元素,即一个数组;如果是这样,那么您可以在函数内部手动取消它。这会让您失去将单个数组作为单个参数传递的能力,我不推荐它。即目前您可以区分

test([1, 2]); // one argument that is an array
test(1, 2);   // two arguments that are strings
Run Code Online (Sandbox Code Playgroud)

有了这样的启发,你将无法再这样做了。


Sal*_*dor 2

它在功能上有不同的结果。

1)如果将多个字符串传递给函数,它将得到一个字符串数组,如下所示:

test('a', 'series of', 'strings go here');

//vardump result
array (size=3)
  0 => string 'a' (length=1)
  1 => string 'series of' (length=9)
  2 => string 'strings go here' (length=15)
Run Code Online (Sandbox Code Playgroud)

2)如果你将一个数组传递给函数,它将得到一个数组的数组。splat 运算符会将传递给函数的第一个条目添加到数组的第一个索引中,第二个参数将添加到第二个索引中,依此类推。因此,无论您将什么传递给函数(数组或字符串),它都会转到索引零。但问题是,如果您传递数组,它将在数组的第一个索引中生成一个数组数组:

test([ 'a', 'series of', 'strings go here' ]);

//vardump result
array (size=1)
  0 => 
    array (size=3)
      0 => string 'a' (length=1)
      1 => string 'series of' (length=9)
      2 => string 'strings go here' (length=15)
Run Code Online (Sandbox Code Playgroud)

结论:

您可以通过以下两种方法之一解决此问题:

1) 在将数组传递给函数之前添加 3 个点:

test(...[ 'a', 'series of', 'strings go here' ]);
Run Code Online (Sandbox Code Playgroud)

2) 另一种方法是添加一个名为 is_multi_array() 的函数来检查传递给该函数的变量是否是多维的。之后,您可以简单地获取数组的第一个元素并将其放入字符串变量中:

function is_multi_array( $arr ) {
    rsort( $arr );
    return (isset( $arr[0] ) && is_array( $arr[0] ));
}

function test(...$strings)
{
   if(is_multi_array($strings)){
       $strings = $strings[0];
   }

   //do the rest
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以按照您喜欢的两种方式使用该函数:

test('a', 'series of', 'strings go here');
test([ 'a', 'series of', 'strings go here' ]);
Run Code Online (Sandbox Code Playgroud)