スプレッド演算子と可変長引数(…)の使いどころ
スプレッド演算子と可変長引数(...)は同じ記号ですが、関数定義側では引数を配列にまとめ、呼び出し側や配列リテラル内では要素を展開する、という逆の意味を持つ機能です。
PHPの...(3点ドット)は、文脈によって「展開」と「まとめ」の逆の意味を持ちます。ここが混乱の元なので整理しておきます。
関数定義では「まとめる」(可変長引数)
function sum(...$numbers): int
{
return array_sum($numbers); // $numbersは配列
}
sum(1, 2, 3); // 6
引数側に書くと、渡された引数を配列としてまとめて受け取ります。個数が決まっていない引数を扱うときに使います。
呼び出しでは「展開する」
$args = [1, 2, 3];
sum(...$args); // 配列を個々の引数に展開して渡す
配列の結合にも使える
$base = ['a', 'b'];
$more = ['c', 'd'];
$all = [...$base, ...$more]; // ['a','b','c','d']
array_mergeより見た目がすっきりします。PHP 8.1からは文字列キーの展開もできるようになりました。
まとめ
定義側の...は集める、呼び出し側・配列リテラル内の...は広げる。同じ記号で逆向きなので最初は戸惑いますが、「どちら側に書いているか」で判断すれば迷いません。可変長引数はarray型の引数で代用できることも多いので、呼び出し側の書きやすさで選ぶといいと思います。
よくある質問
Q. 同じ…なのに意味が逆で混乱します。
A. 関数定義側に書けば引数を配列にまとめ、呼び出し側や配列リテラル内に書けば要素を展開します。「どちら側に書いているか」で判断すれば迷いません。
Q. 文字列キーの配列も…で展開できますか。
A. PHP 8.1から文字列キーの展開もできるようになりました。それ以前は数値キーのみが対象です。