Destructuring Assignment

One thing I love and use all the time is Destructuring Assignment.

You can do this in PHP, JavaScript, on any object or array and if often used in JavaScript frameworks like React, example:

const [ state, setState ] = useState();

Before we go on, I’d like to mention that all examples are in JavaScript, I do have a few examples in PHP at the end of the article.

Wait what does it do?

To destruct is simply to extract or unpack the parts you need from an array or object, here’s an example where I want to store the first and second value from an array in their individual variables and how to do it without and with destruct:

The None-Destruct way

let myArray = [
    'Item 0',
    'Item 1',
    'Item 2',
    'Item 3',
];

let item0 = myArray[0];
let item1 = myArray[1];

The Destruct way

let myArray = [
    'Item 0',
    'Item 1',
    'Item 2',
    'Item 3',
];

let [ item0, item1 ] = myArray;

And here’s an example using objects:

The None-Destruct way

let myObject = {
    item0: 'Value 0',
    item1: 'Value 1',
    item2: 'Value 2',
    item3: 'Value 3',
};

let item0 = myObject.item0;
let item1 = myObject.item1;

The Destruct way

let myObject = {
    item0: 'Value 0',
    item1: 'Value 1',
    item2: 'Value 2',
    item3: 'Value 3',
};

let { item0, item1 } = myObject;

If you look closely at both the array example and the object example you can see that I’ve wrapped brackets and curly brackets around the variables item0 and item1 let and before the equal sign.

The behaviors are similar but a bit different depending on if it’s an array or object so let’s look at arrays first!

Array Destructing

When you destruct an array, it will take each value from the array in the same order and place them in whatever variable name you give it.

That means you can name the variables whatever you wish (just keep in mind in what order the array items are in), example:

Here I’ve created an array with info about myself like first name, last name, and age, then using destruct I’ve unpacked the values into corresponding variables.

The key here is to wrap the variables in bracket (if it’s an array and curly if it’s an object) and then assign them from the myInfo array.

The thing to keep in mind here is that you will always get each value in the array order of it but if you want to skip some values you can do it like this:

let myInfo = [ 'Thomas', 'Karlsson', 33 ];
let [ , , age ] = myInfo;

By just adding commas I’ve essentially jumped over the first two values and only stored the third item in my age variable.

Object Destructing

When you destruct an object, it is similar to an array except here you need to define the exact key you want to unpack into its own variable, example:

let myInfo = { 
    firstName: 'Thomas', 
    lastName: 'Karlsson', 
    age: 33 
};

let { firstName, lastName, age } = myInfo;

Unlike an array however you do not need to go in order or use any commas if you only want specific values, just use the same keys in any order you wish to extract those values, example:

let myInfo = { 
    firstName: 'Thomas', 
    lastName: 'Karlsson', 
    age: 33 
};

let { age, lastName } = myInfo;

Here we ignore firstName and extract age first even though it’s last in the object

There is a way however if you want to rename the variable you unpack from the object, example:

let myInfo = { 
    firstName: 'Thomas', 
    lastName: 'Karlsson', 
    age: 33 
};

let { lastName:lName } = myInfo;

Here we ignore firstName and extract age first even though it’s last in the object

In this example I’ve extracted the key lastName from myInfo into a variable called lname.

This is useful if you have multiple objects you wish to destruct that all have the same keys, example:

let myInfo = { 
    firstName: 'Thomas', 
    lastName: 'Karlsson', 
    age: 33 
};
let { lastName:myLastName} = myInfo;

let yourInfo = { 
    firstName: 'John', 
    lastName: 'Doe', 
    age: 19
};
let { lastName:yourLastName} = yourInfo ;

Here we ignore firstName and extract age first even though it’s last in the object

Destructing Nested Objects/Arrays

You might ask yourself then “What do I do if I have objects and arrays inside my object/array?“, well don’t worry my friend cause we can extract those values as well, here’s an example how:

let myInfo = {
    firstName: 'Thomas',
    lastName: 'Karlsson',
    age: 33,
    location: {
        country: 'Sweden',
        city: 'Malmo',
    },
    skills: [
        'JavaScript',
        'PHP',
    ],
};

let {
    location: { country },
    skills: [ skill0 ],
};

So, what’s going on here?

Well inside our object we have added an object named location then using destruct I’ve taken the key country inside it and unpacked it into a variable with the same name.

We have also added an array named skills in wish I’ve taken out the first item and stored it in a variable named skill0.

Keep in mind that location and skills are NOT unpacked into their own variable when using destruct on them, if I also would like them to be unpacked into their own variables, I would have to write something like this:

let myInfo = {
    location: {
        country: 'Sweden',
        city: 'Malmo',
    },
    skills: [
        'JavaScript',
        'PHP',
    ],
};

let {
    location,
    location: { country },
    skills,
    skills: [ skill0 ],
};

Fallback Values

My favorite thing about destruct is fallback values.

If you use a key in an object or array does not exists it will still create that variable, but the value will be undefined, example:

In the above image I’m running the example code in chromes developer console.

We can see that myObject only has one called item0, however lower down when I use destruct, I’m calling a variable called item1 (which does not exist in the object).

When we console.log this value it will show as undefined.

This is very useful if for example we call an API and we’re not sure we’re going have a piece of data available, we can still unpack it in a variable and just run a simple if statement, example:

const res = await fetch('https://some.route/');
const json = await res.json();

const { currentTemperature } = json;

if( currentTemperature ){
    // Your code...
}

There are of course many other ways to do this without destruct, for example Optional Chaining.

We can also set a default fallback value in case the key is undefined, example:

let myObject = {
    item0: 'Value 0'
};

let { item1 = 'Value 1' } = myObject;

In this example we’re trying to unpack the object key item1 and if it does not exist, we will assign it a fallback value of Value 1.

This will also work on arrays, example:

let myArray = [
    'Item 0'
];

let [
    item0 = 'Item 0',
    item1 = 'Item 1',
] = myArray;

PHP Examples

As I mentioned in the top of the article you can also destruct in PHP, here’s a couple of examples and what versions support this syntax.

This will work in PHP 7.1 and forward

$myArray = [
    'Item 0',
    'Item 1',
    'Item 2',
];

[ $item0, $item1 ] = $myArray;

You can also destruct an array with string keys from PHP 8.1 and forward.

$myArray = [
    'item0' => 'Value 0',
    'item1' => 'Value 1',
    'item2' => 'Value 2',
];

[ 
    'item0' => $item0, 
    'item1' => $item1, 
] = $myArray;

We cannot destruct objects but we can get around this by typecasting it to a array, example:

[ 
    'item0' => $item0, 
    'item1' => $item1, 
] = (ARRAY) $myObject;

Unlike JavaScript if a key does not exist in array/object this will generate a warning in the logs, there are a few ways to get around this and I will showcase a few ways.

Solution 1: The Error Control Operator

This is slightly controversial as it may hide useful errors messages however if you know what you’re doing I would say it’s perfectly fine.

All you have to do is add an @ sign in front of the array like this:

@[ 
    'item0' => $item0, 
    'item1' => $item1, 
] = $myArray;

This will suppress any warnings and still generate variables with NULL if there is no key in the array.

Solution 2: Default Values

$myArray = [
    'item0' => 'Value 0',
];

$defaultValues = [
    'item0' => 'Value 0',
    'item1' => 'Value 1',
    'item2' => 'Value 2',
];

[ 
    'item0' => $item0, 
    'item1' => $item1, 
] = $myArray + $defaultValues;

In this example we have an array called $defaultValues with the fallback values and then combined them with $myArray.

The reason we use + and not array_merge is cause array_merge will not preserve numeric keys.

Real Life Examples

I want to end with a typical example you might experience, let’s say you are calling an API route and it will always return an array, this array will on most cases have an object but sometimes it will send an empty array where there is no data, here’s how you could deal with that:

const res = await fetch('https://some.route/');
const json = await res.json();

const [ data = {} ] = json;

const {
    title = 'No data',
    description = 'Come back later'
} = data

What’s neat in this example is that we can destruct the data variable in the end even if the API returns an empty array, this is because we assign an empty object to it if the array is empty!

You should however add more checks in case the API changes but hopefully this example shows the possibilities.

I hope this was useful and that you’ll have an easier time when you build your project or navigate other people’s code in the future!