I work on javascript/typescript on a constant basis, and php on an infrequent basis (on my legacy php app http://www.ninjawars.net).
When I switch back to php after a long time of using javascript or typescript, I really miss the clean code that you can write by using destructuring.
Now, I talked a bit in another post about short circuit evaluation in js vs php as a way to make code terser and with much less boilerplate, but what about destructuring in php?
Destructuring in js
First, let's glance at destructuring in js:
const {a, b, c, ...rest} = {a:'Apple', b:'Banana', c:'Cantalope', d:'Durian'}
...not only is destructuring smooth, it also allows for the powerful ...rest
spread syntax. I can't tell you the number of times that I have had some complex code block in javascript that was simplified by converting it to use destructuring, or perhaps avoiding an undefined property that destructuring handles smoothly, like:
property api.data.user.name may be undefined
// The dreaded chain of && to avoid undefined properties
if(api && api.data && api.data.user && api.data.user.name){
const username = api.data.user.name || 'unknown' // finally do something
}
another approach using the optional chaining operator from typescript:
const username = api?.data?.user?.name || 'Unknown user'
But here's another option, using destructuring:
const { data={} } = api
const { user={} } = data
const { name='Unknown' } = user
console.log(name) // Unknown
Destructuring in php
Sadly, php only supports a very limited bit of destructuring, specifically, when destructuring arrays, by using list()
destructuring or []
destructuring.
[$a, $b, $c] = ['apple', 'banana', 'cantaloupe'];
OR
[,,,$d,$e] = ['apple', 'banana', 'cantaloupe', 'durian', 'eggplant'];
Thankfully, you are also allowed to destructure named keys from associative arrays:
$fruit = [
'a'=>'apple',
'b'=>'banana',
'c'=>'cantaloupe',
'd'=>'durian',
'e'=>'eggplant'
];
// Have to set the $fruit var because for some reason php doesn't like it when you try to directly destructure from the associative array you just created.
['d'=>$d, 'e'=>e] = $fruit;
echo $d; // Durian now
echo $e; // Eggplant
So as long as you are dealing with an array or an associative array you can do some destructuring.
Destructuring php objects
It's somewhat possible to destructure a php object by transforming it into an array.
$api = {
data: {
user: {
name: 'George Washington'
}
}; // A nested data object
To destructure this you generally have to turn it into an array first, and deal with the proposition of turning it's nested properties into arrays as well. This may be a diminishing return on effort.
What about ...spreading values?
More modern versions of php, at least 8+, support spread/splat operators on arrays in weird ways, having supported spread operators on function arguments since way back in php 5.6.
Spread on arrays in php:
$fruit = ['apple', 'banana', 'canteloupe', 'durian'];
[$a, ...$rest] = $fruit;
var_dump($rest); // ['banana', 'canteloupe', 'durian']
For whatever reason, you have to assign to a variable before you can then destructure that variable. Immediately destructuring a variable that you are just assigning causes a php error that says:
PHP Fatal error: Spread operator is not supported in assignments in php shell code on line 1
So the spread operator exists, and it works, you just can't use destructuring immediately upon assignment in php.
The takeaway
Still, there is a lot of potential for destructuring as a way to clean up and simplify code.
Top comments (2)
I don't think
[$a, ...$rest] = $fruit;
works.Actually, I'm pretty sure it doesn't work, as I've just spent ages applying latest PHP versions and no β it doesn't work, at least for me.
Thanks Roy! This was helpful.