01 · THE IDEAREAD → TRY → LEARN
Why unpack arguments?
Sometimes the values a function needs already sit in an array: a row of parsed input, a configuration list, or the result of another function. Writing $row[0], $row[1], $row[2] by hand is noisy and breaks as soon as the array grows. PHP's ... operator solves this. Placed in front of an array or Traversable inside a call, it expands the elements into separate arguments.
Do not confuse this with the variadic parameter function sum(...$numbers). That form collects arguments into an array when a function is declared. Unpacking is the opposite direction: it spreads an array into arguments when a function is called. They are often used together, but they are different jobs.
The basic form
The arguments in a call are evaluated left to right and assigned to parameters in order. With unpacking, the first array element becomes the first argument, the second becomes the second, and so on.
function add(int $a, int $b): int
{
return $a + $b;
}
$pair = [4, 6];
echo add(...$pair), "\n";
echo add(...[1, 2]), "\n";10 3
You can unpack a variable or an array literal. The function does not know the values came from an array; it just receives two arguments.
Mixing with ordinary arguments
You may write normal arguments before an unpacked array, and you may unpack more than one array in the same call. Defaults still apply: if the array supplies fewer values than there are parameters, the remaining parameters fall back to their default values. If a required parameter receives nothing, PHP throws an ArgumentCountError.
function label(string $prefix, string $name, string $suffix = ''): string
{
return $prefix . $name . $suffix;
}
$rest = ['Ada', '!'];
echo label('Hi ', ...$rest), "\n";
$parts = ['Hi ', 'Bob'];
echo label(...$parts), "\n";Hi Ada! Hi Bob
In the first call the literal 'Hi ' fills $prefix, then the array fills $name and $suffix. In the second call the array has only two items, so $suffix keeps its default empty string.
String keys and named arguments
If the array has string keys, each key is treated as a parameter name. This works because PHP supports named arguments. Order then does not matter, but every key must match a real parameter, and a key must not repeat a parameter that already received a value. Since PHP 8.1 you can also write a named argument after an unpacked array, provided it does not overwrite something already unpacked.
function box(int $w, int $h, int $d = 1): int
{
return $w * $h * $d;
}
echo box(...['h' => 3, 'w' => 2]), "\n";
echo box(...[2, 3], d: 4), "\n";
echo json_encode([box(...[5, 5])]), "\n";6 24 [25]
The first call uses keys to fill $w and $h. The second unpacks two positional values and names $d explicitly. The third relies on the default depth of 1.
Common mistakes
- Passing the array itself.
box($dimensions)sends one array argument to anintparameter and causes aTypeError. You needbox(...$dimensions). - Too few values. An array with one element cannot satisfy two required parameters.
- Too many values. For a user-defined function without a variadic parameter, extra positional arguments are ignored, which can hide bugs. Unknown string keys, however, raise an error.
- Conflicting names. A named argument that targets a parameter the unpacked array already filled throws an
Error. - Forgetting types. Unpacked values are still checked against parameter types in the usual way.
Exercise contract
The starter file already defines a helper volume(int $w, int $h, int $d = 1): int. Your job is to write boxVolume(array $dimensions): int. It receives a list of two or three integers and must return the volume by passing the list to volume() using unpacking. A two-item list uses the default depth of 1, so [2, 3] gives 6 and [2, 3, 4] gives 24. Zero is a valid dimension and produces 0. The tests check the returned integer, not printed output.
Recap
Use ... in a call to spread an array into arguments. Positional elements fill parameters in order, string keys fill parameters by name, and defaults cover whatever is left. Combine it with ordinary and named arguments when needed, and remember that you are spreading values, not changing the function itself.
Functions · Arrays · Types
- Pass positional argument arrays to functions
- Implement and test a deterministic PHP 8.4 function