Destructuring and Spread
Destructuring unpacks an array into separate variables in one statement. The spread operator ... does the opposite: it expands an array into a list of elements or arguments. Together they make code that handles rows, pairs and lists of arguments much shorter and clearer.
Destructuring lists
Put variables in square brackets on the left of an assignment, and the array's elements are assigned to them in order:
<?php $point = [3, 7]; [$x, $y] = $point; echo "x=$x y=$y\n"; [$first, , $third] = ["a", "b", "c"]; // skip an element echo "$first $third\n"; $a = 1; $b = 2; [$a, $b] = [$b, $a]; // swap echo "$a $b\n";
x=3 y=7 a c 2 1
The older list($x, $y) = $point; syntax does the same thing.
Destructuring by key
For associative arrays, name the keys you want. Order doesn't matter, and you can take only some of them:
<?php $user = ["id" => 42, "name" => "Ana", "email" => "ana@example.com", "role" => "admin"]; ["name" => $name, "role" => $role] = $user; echo "$name is an $role\n";
Ana is an admin
Destructuring in foreach
Unpacking each row right in the loop header is one of the most useful forms:
<?php $cart = [ ["Pen", 1.20, 10], ["Notebook", 3.50, 4], ]; foreach ($cart as [$item, $price, $qty]) { printf("%-9s %2d x %.2f\n", $item, $qty, $price); } $people = [["name" => "Ana", "age" => 34], ["name" => "Ben", "age" => 27]]; foreach ($people as ["name" => $n, "age" => $a]) { echo "$n ($a)\n"; }
Pen 10 x 1.20 Notebook 4 x 3.50 Ana (34) Ben (27)
Returning several values
A function can return an array, and the caller can destructure it immediately:
<?php function minMax(array $values): array { return [min($values), max($values)]; } function parseName(string $full): array { $parts = explode(" ", $full, 2); return ["first" => $parts[0], "last" => $parts[1] ?? ""]; } [$lo, $hi] = minMax([14, 9, 21, 17, 6]); echo "min $lo, max $hi\n"; ["first" => $f, "last" => $l] = parseName("Grace Brewster Hopper"); echo "$l, $f\n";
min 6, max 21 Brewster Hopper, Grace
Nested destructuring
<?php $line = ["from" => [0, 0], "to" => [3, 4]]; ["from" => [$x1, $y1], "to" => [$x2, $y2]] = $line; echo sqrt(($x2 - $x1) ** 2 + ($y2 - $y1) ** 2), "\n";
5
Missing elements
If the array is shorter than the pattern, the extra variables become null with a warning. Check the length first, or pad the array:
<?php [$a, $b] = array_pad(explode(":", "host"), 2, "80"); echo "$a $b\n"; [$c, $d] = explode(":", "host");
host 80 Warning: Undefined array key 1 in main.php on line 6
The spread operator in arrays
...$array inside an array literal inserts all of its elements. It works with string keys too (later keys win, like array_merge):
<?php $low = [1, 2, 3]; $high = [8, 9]; $all = [0, ...$low, 5, ...$high]; echo implode(", ", $all), "\n"; $defaults = ["theme" => "light", "size" => 14]; $settings = [...$defaults, "size" => 16, "lang" => "pt"]; print_r($settings);
0, 1, 2, 3, 5, 8, 9
Array
(
[theme] => light
[size] => 16
[lang] => pt
)Spreading arguments
When calling a function, ...$args passes each element as a separate argument. With string keys, they become named arguments (lesson 28):
<?php function volume(float $length, float $width, float $height): float { return $length * $width * $height; } $dims = [2, 3, 4]; echo volume(...$dims), "\n"; echo max(...[3, 9, 4]), "\n"; $named = ["height" => 10, "length" => 1, "width" => 2]; echo volume(...$named), "\n";
24 9 20
Collecting arguments: variadic functions
The same three dots in a function's parameter list collect any number of arguments into an array:
<?php function average(float ...$numbers): float { return $numbers === [] ? 0 : array_sum($numbers) / count($numbers); } echo average(4, 8, 15, 16, 23, 42), "\n"; echo average(), "\n"; $data = [1, 2, 3]; echo average(...$data), "\n";
18 0 2
Try it yourself
Parse lines of "name,city,score" with explode and destructuring, then print a summary.
Ana from Lisbon scored 82 Ben from Leeds scored 91 Cleo from Lisbon scored 77 Best 91, worst 77