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

How to make PHP understand *either* an array or the splat operator (3 dots ...) for function parameters?

我有这个代码:

function test(...$strings)
{
    // ...
}

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

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

哪个有效。但是,我经常想这样做:

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

或者:

test($an_array_of_strings);

事实上,当我开始收到关于 "Array to string conversion".

的错误时,我非常确定这有效,以至于我感到震惊和困惑

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

因为它(显然)没有,是否有某种方法可以在不必使用两个单独的函数的情况下完成此操作?我不想分开:

function test_array($strings = [])
{
    // ...
}

反过来也是一样:

test(...$an_array_of_strings);

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

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

有了这样的启发式方法,您将无法再这样做了。

在函数中有不同的结果。

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)

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

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)

结论:

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

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

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

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

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
}

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

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