PHP Array Destructuring

Chapter 29 14 mins

Learning outcomes:

  1. What is array destructuring
  2. How to destructure arrays (using [] or list())
  3. Examples of array destructuring
  4. Destructuring with assign-by-reference (&)
  5. Using destructuring with foreach

Introduction

Arrays are exceptionally useful in our day-to-day programs, be they in any modern high-level programming language. In PHP, as we've seen so far, there is a lot of potential in the array data type. We can have indexed arrays modeling sequences of data or we can associative arrays modeling dictionary-like data, with key-value pairs.

Another set of equally useful concepts related to arrays in PHP is that of destructuring and unpacking.

From a technical standpoint, both of these concepts refer to extracting elements out of an array into the surrounding context. The nature of that extraction is, however, different between these two.

In this chapter, we'll go over array destructuring in detail. In particular, we'll start by understanding what exactly is meant by destructuring; how to perform it using list(); the relatively modern syntax of destructuring; and finally wrap up the chapter with a handful of examples.

So without spending more of our time here, let's get to work.

What is array destructuring?

By definition:

Array destructuring is a means of assigning to given variables the elements of an array in one go.

If you look up the meaning of 'destructure', it means to 'extract something out of the main part'. That's exactly what array destructuring means, i.e. to literally 'extract' elements out of an array and then dump them into given variables.

Said another way, where 'structure' means to put things together into one single thing, 'destructure' means to break that one single thing down to smaller, individual things.

It's important to realize at this stage that we can extract elements out of an array without destructuring as well. Remember how to access individual elements of an array in PHP? Using bracket notation.

So then why do we even need destructuring? Well, it's a really handy shortcut for extraction.

Let's see what this means with the help of an example.

Suppose we have an array holding the RGB components of a given pixel, as shown below:

<?php

// Represents the color rgb(10, 50, 255).
$pixel = [10, 50, 255];

What we're interested in over here is to assign each component of the pixel to a separate variable.

Clearly this ain't difficult at all — manually access each individual element and then assign it to the desired variable:

<?php

// Represents the color rgb(10, 50, 255).
$pixel = [10, 50, 255];

$red = $pixel[0];
$green = $pixel[1];
$blue = $pixel[2];

echo "$red $green $blue";
10 50 255

But as it turns out, this is such a common and repetitive task in complex programs that, over the years, languages have come to provide a conciser and easier syntax to accomplish it.

That easier syntax is what we refer to, at least in PHP, as array destructuring.

What we're doing above in three lines can be effectively done in just one line. Better yet, we don't even need to use indexes. Isn't that elegant?

Let's see how to destructure arrays in PHP.

How to destructure arrays?

Prior to PHP version 7.1.0, there was only one way to destructure arrays. However, with the advent of version 8.0, we now have two ways.

They are as follows:

  1. The [] notation (introduced in PHP 8.0)
  2. The list() construct

We'll focus on the former, i.e. using [], since it's syntactically more concise. All the ideas that apply to destructuring via [] also apply to destructuring via list().

Here's how array destructuring goes by for an indexed array:

[$var_1, $var_2, ...] = $array;

The left-hand side here doesn't denote an array of values; rather, it denotes the syntax for destructuring the array on the right-hand side.

That is, it specifies that the first element of $array should be assigned to the variable $var_1, the second element should be assigned to $var_2, and so on.

Note that it's not required for the variables to be defined before we use them in a destructuring statement; if they don't exist, they're created.

At the end of the day, destructuring is just assigning the elements of an array to given variables. So even if a variable doesn't exist, it makes perfect sense that it'll get created.

Destructuring is also possible on associative arrays. Here's how it'll generally look:

[$key_1 => $var_1, $key_2 => $var_2, ...] = $array;

With the syntax out of the way, let's now see a couple of examples of destructuring arrays in PHP, starting with an RGB example shown above.

Destructuring examples

Let's recall the code above that extracted elements out of the $pixel array into individual variables $red, $green and $blue:

<?php

$pixel = [10, 50, 255];

$red = $pixel[0];
$green = $pixel[1];
$blue = $pixel[2];

echo "$red $green $blue";

As stated, destructuring can make this a lot simpler. Time to see it in action:

<?php

$pixel = [10, 50, 255];

[$red, $green, $blue] = $pixel; echo "$red $green $blue";

The most important line here is obviously line 5. Let's see what's going on in there...

[$red, $green, $blue] lists the variables that'll be assigned values from the $pixel array; precisely, the first, second, and third elements, respectively.

When we run the code, we see the exact same output as before:

10 50 255

This confirms that our destructuring went absolutely fine. Perfect!

Now what do you say? Which syntax seems better when all what you want to do is to take an array and assign its elements to individual variables?

What's remarkable about destructuring is that we can play around with it in a multitude of ways, to cater to a wide number of use cases.

Skipping elements

As one example, suppose we are only interested in the green and blue components in $pixel above and, therefore, only need to create $green and $blue.

One way is to skip writing anything as the first element in the destructuring block:

<?php

$pixel = [10, 50, 255];

// The first element in the destructuring block is omitted,
// likewise the first element of $pixel goes nowhere.
[, $green, $blue] = $pixel;

echo "$green $blue";
50 255

PHP realizes that first element in the destructuring block is omitted and, likewise, ignores processing the corresponding element in the array.

Another option is to explicitly key the variables:

<?php

$pixel = [10, 50, 255];

// The element at index 1 in $pixel goes into $green.
// The element at index 2 goes into $blue.
[1 => $green, 2 => $blue] = $pixel;

echo "$green $blue";
50 255

At least in this case, this latter option doesn't make that much of sense. It's an overkill.

Destructuring with keys usually makes sense, and should ideally only be used, when we are dealing with associative arrays.

Swapping variables

As another example, suppose we want to swap two variables with one another. As with many things in programming, swapping is a super elementary, yet extremely crucial, operation employed in many algorithms.

The standard way to perform swapping is to create a $temp variable to temporarily hold a variable's value while we assign the value of the other variable to it.

Something along the following lines:

<?php

$a = 10;
$b = 20;

// Swapping
$temp = $a;
$a = $b;
$b = $temp;

echo "$a $b";
20 10

But thanks to array destructuring, we can accomplish this three-line operation in just one single statement in PHP:

<?php

$a = 10;
$b = 20;

// Swapping using destructuring
[$a, $b] = [$b, $a];

echo "$a $b";
20 10

Making intuition of this code is pretty easy: first [$b, $a] (on the right-hand side of =) defines an array whose first element is $a and second element is $b.

Then, [$a, $b] (on the left-hand side) commands that the first element of this array, which is $b, gets assigned to $a while the second element, which is $a, gets assigned to $b.

And that's it. Swapping done.

Destructuring with assign-by-reference

We learnt back in the PHP References chapter that in order to assign an entity to another entity by reference, we use assign-by-reference (=&). An array is also an entity so this idea applies to arrays as well.

For example, let's say that in our RGB example, we want each of the three variables to be references to the corresponding elements in $pixel.

Manually using &=, this will mandate the following code:

<?php

$pixel = [10, 50, 255];

$red =& $pixel[0];
$green =& $pixel[1];
$blue =& $pixel[2];

$red = 255;
print_r($pixel);
Array ( [0] => 255 [1] => 50 [2] => 255 )

Luckily, destructuring in PHP has this capability built into it.

The syntax is similar to how we use references in function parameters and in foreach, i.e. the variable is prefixed with an ampersand (&).

Here's how we could express it generally:

[&$var_1, &$var_2, ...] = $array;

Based on this, let's rewrite the code above using destructuring:

<?php

$pixel = [10, 50, 255];

[&$red, &$green, &$blue] = $pixel; $red = 255; print_r($pixel);
Array ( [0] => 255 [1] => 50 [2] => 255 )

Destructuring is fantastic, isn't it?

Although it might be evident already, but just to state it explicitly, it's NOT required to label all the variables in a destructuring block as references. We only need to do so with those variables that we want to make references.

So for example, the following code, where only $red is assigned-by-reference, is perfectly legal:

<?php

$pixel = [10, 50, 255];

// $green and $blue aren't assigned by-reference here.
[&$red, $green, $blue] = $pixel;

$red = 255;
print_r($pixel);

Using destructuring in foreach

We know that the foreach loop is used to iterate over arrays in PHP.

We also know that there are a handful of variations of it — one extracting values only; one extracting values and keys; one extracting values only, with references; and one with extracting values, with references, and keys.

Another variation is to use destructuring directly in the loop's header. This obviously only makes sense when we're dealing with 2D arrays because only in that way would each element of the main array be an an array itself which is then ultimately destructured.

Suppose we have the following array where each element (which is an array itself) represents dimensions of a right-angled triangle:

<?php

$triangles = [
   [3, 4],
   [5, 12],
   [28, 45]
];

Our job is to calculate the length of the hypotneuse of each of these triangles and then echo it.

Let's do it:

<?php

$triangles = [
   [3, 4],
   [5, 12],
   [28, 45]
];

foreach ($triangles as [$a, $b]) {
   echo ($a ** 2 + $b ** 2) ** 0.5, "\n";
}
5 13 53

Two things are remarkable here: one is the destructuring syntax used in foreach's header, whereas the second is the Pythagorean Theorem used to compute the hypotneuse.