Array Destructuring
What Is Array Destructuring?
In simple terms: Destructuring unpacks values from an array into separate variables in one statement. Instead of writing $day = $parts[0]; $month = $parts[1]; $year = $parts[2];, you write [$day, $month, $year] = $parts;.
Technically: When an array literal pattern appears on the left side of an assignment, PHP assigns elements of the right-side array to the variables in the pattern — by position for list-style patterns, or by key for keyed patterns. The older list() construct does the same thing; the short [] syntax has been available since PHP 7.1.
Why It Is Useful
- Functions can effectively return several values:
[$min, $max] = minMax($numbers); - Split strings into named parts:
[$user, $domain] = explode('@', $email); - Unpack records in loops:
foreach ($points as [$x, $y]) - Swap variables without a temporary variable
The result is shorter code with meaningful variable names instead of numeric indexes.
Positional Destructuring
Syntax
[$first, $second, $third] = $array;
Example
<?php
$date = '15/10/2026';
[$day, $month, $year] = explode('/', $date);
echo "Day: $day, Month: $month, Year: $year\n";
Output
Day: 15, Month: 10, Year: 2026
How It Works
explode('/', $date)returns['15', '10', '2026'].- The pattern
[$day, $month, $year]assigns element0to$day, element1to$month, and element2to$year.
Positional destructuring reads keys 0, 1, 2, … — it does not matter in which order the elements were added, only what their integer keys are.
The list() Syntax
list($day, $month, $year) = explode('/', '15/10/2026');
This is identical to the [] form. You will see list() in older code; use [] in new code.
Skipping Elements
Leave a position empty to skip it:
<?php
$row = ['ORD-501', 'Asha', 'Chennai', 1250, 'paid'];
[$orderId, , , $amount, $status] = $row;
echo "$orderId: ₹$amount ($status)\n";
Output
ORD-501: ₹1250 (paid)
The empty positions skip the customer name and city. For records with many fields, keyed destructuring (next section) is clearer than counting commas.
Keyed Destructuring
For associative arrays, specify the keys to extract:
<?php
$user = [
'id' => 7,
'name' => 'Asha',
'email' => 'asha@example.com',
'city' => 'Chennai',
];
['name' => $name, 'email' => $email] = $user;
echo "$name <$email>\n";
Output
Asha <asha@example.com>
- Only the listed keys are extracted;
idandcityare ignored. - The order does not matter:
['email' => $email, 'name' => $name] = $user;works the same. - Variable names can differ from the keys:
['name' => $customerName] = $user;.
Positional and keyed patterns cannot be mixed in the same destructuring.
Nested Destructuring
Patterns can be nested to reach into inner arrays:
<?php
$order = [
'id' => 501,
'customer' => ['name' => 'Asha', 'city' => 'Madurai'],
'items' => [
['name' => 'Gel Pen', 'qty' => 10],
['name' => 'Notebook', 'qty' => 3],
],
];
[
'id' => $orderId,
'customer' => ['name' => $customerName],
'items' => [['name' => $firstItem]],
] = $order;
echo "Order $orderId for $customerName, first item: $firstItem\n";
Output
Order 501 for Asha, first item: Gel Pen
Each nested pattern matches the structure at that level. Deep nesting quickly becomes hard to read, so keep nested destructuring to one or two levels.
Destructuring in foreach
Destructuring each element directly in the loop header is one of the most useful forms:
<?php
$points = [[3, 4], [6, 8], [5, 12]];
foreach ($points as [$x, $y]) {
$distance = sqrt($x ** 2 + $y ** 2);
echo "($x, $y) is $distance units from the origin\n";
}
$orders = [
['id' => 101, 'customer' => 'Asha', 'total' => 1250],
['id' => 102, 'customer' => 'Bala', 'total' => 640],
];
foreach ($orders as ['id' => $id, 'total' => $total]) {
echo "Order $id: ₹$total\n";
}
Output
(3, 4) is 5 units from the origin
(6, 8) is 10 units from the origin
(5, 12) is 13 units from the origin
Order 101: ₹1250
Order 102: ₹640
The loop body uses meaningful names ($x, $total) instead of $point[0] or $order['total'].
Returning Multiple Values From Functions
<?php
function minMax(array $numbers): array
{
return [min($numbers), max($numbers)];
}
function splitEmail(string $email): array
{
return explode('@', $email, 2);
}
[$lowest, $highest] = minMax([42, 7, 19, 88]);
[$user, $domain] = splitEmail('karthik@gocourse.in');
echo "Range: $lowest – $highest\n";
echo "User: $user, domain: $domain\n";
Output
Range: 7 – 88
User: karthik, domain: gocourse.in
The caller chooses descriptive names for each returned value. For more than two or three values, return an associative array and use keyed destructuring, so the meaning of each value is explicit.
Swapping Variables
<?php
$left = 'A';
$right = 'B';
[$left, $right] = [$right, $left];
echo "$left $right\n";
Output
B A
The right side builds a new array ['B', 'A'] first, and then the destructuring assigns it — no temporary variable needed.
Missing Elements and Defaults
If the array lacks an element that the pattern expects, PHP raises a warning and assigns null:
<?php
[$a, $b, $c] = [1, 2];
var_dump($c);
Output
PHP Warning: Undefined array key 2 in /path/script.php on line 2
NULL
Destructuring has no built-in default values. Common solutions:
<?php
$config = ['host' => 'db.internal'];
// Merge defaults before destructuring
['host' => $host, 'port' => $port] = $config + ['host' => 'localhost', 'port' => 3306];
echo "$host:$port\n";
// Pad lists to the expected length
[$first, $second, $third] = array_pad(['only one'], 3, null);
var_dump($third);
Output
db.internal:3306
NULL
$config + $defaultskeeps the existing values and adds missing keys from the defaults.array_pad()extends a list to a fixed length, so every position exists.
Using a Limit With explode()
When destructuring the result of explode(), use a limit to control how many parts are produced:
<?php
[$key, $value] = explode('=', 'redirect_url=https://example.com/?a=1', 2);
echo "$key → $value\n";
Output
redirect_url → https://example.com/?a=1
Without the limit 2, the = inside the URL would create extra parts, and the second variable would receive only https://example.com/?a.
Destructuring by Reference (PHP 7.3+)
Prefixing a variable with & makes it a reference to the array element:
<?php
$prices = [100, 200];
[&$first, $second] = $prices;
$first = 150;
print_r($prices);
Output
Array
(
[0] => 150
[1] => 200
)
Changing $first changes $prices[0]. Use this sparingly; it is easy to forget that the variable is linked to the array.
Practical Example: Parsing Log Lines
<?php
$log = [
'2026-10-09 10:15:02|INFO|User asha logged in',
'2026-10-09 10:16:45|ERROR|Payment failed: card declined | retrying',
'2026-10-09 10:17:10|INFO|Order 501 created',
];
$counts = [];
foreach ($log as $line) {
[$timestamp, $level, $message] = explode('|', $line, 3);
[, $time] = explode(' ', $timestamp);
$counts[$level] = ($counts[$level] ?? 0) + 1;
if ($level === 'ERROR') {
echo "[$time] $message\n";
}
}
foreach ($counts as $level => $count) {
echo "$level: $count\n";
}
Output
[10:16:45] Payment failed: card declined | retrying
INFO: 2
ERROR: 1
Step-by-Step Explanation
explode('|', $line, 3)splits each line into at most three parts, so a|inside the message stays part of the message.- Positional destructuring gives each part a meaningful name.
[, $time] = explode(' ', $timestamp)skips the date and keeps only the time.- The level is used as a key to count entries per level.
Common Mistakes
Mismatched Number of Elements
Effect: "Undefined array key" warnings and null values.
Fix: Validate the array length, use array_pad(), or merge defaults.
Positional Patterns on Associative Arrays
Effect: [$name, $email] = $user; looks for keys 0 and 1, which do not exist.
Fix: Use keyed destructuring: ['name' => $name, 'email' => $email] = $user;.
Forgetting the explode() Limit
Effect: Values containing the separator are cut into extra parts.
Fix: Pass the maximum number of parts as the third argument.
Mixing Keyed and Positional Patterns
Effect: Compile-time error.
Fix: Use one style per pattern.
Overly Deep Nested Patterns
Effect: Hard-to-read code and confusing errors when the structure changes.
Fix: Destructure one level at a time, or use objects for complex data.
Best Practices
- Use
[]destructuring (notlist()) in modern code. - Prefer keyed destructuring for associative arrays and records.
- Destructure directly in
foreachheaders for readable loops. - Combine with
explode()limits,array_pad(), or default arrays to handle missing data. - Return small arrays from functions when a few related values belong together; use objects for larger structures.
Official reference: https://www.php.net/manual/en/language.types.array.php#language.types.array.syntax.destructuring