skip to content

In PHP, how do you destructure an array into separate variables with [] or list(), both by position and by key?

level: juniorimportance: must knowfreq 55%

answer

  1. an array pattern on the left of =
  2. positional reads keys 0, 1, 2
  3. 'lat' => $lat picks by key
  4. empty slot skips an element
  5. [$a, $b] = [$b, $a] swaps

basics

~20 s

Put an array pattern on the left of =: [$lat, $lng] = $point copies the elements at keys 0 and 1, and ['lat' => $lat] = $point copies by key. list() is the older spelling of the same construct.

solid answer

~40 s

Destructuring assigns several variables from one array in a single statement. The short form `[$lat, $lng] = $point;` and the older `list($lat, $lng) = $point;` are the same construct. A **positional** pattern reads keys `0`, `1`, `2`, … in that order, not "the first and second elements". A **keyed** pattern names the keys: `['lat' => $lat, 'lng' => $lng] = $point;`, and the keys can be any expression. Leave a slot empty to skip an element (`[, $lng] = $point`), nest patterns for nested arrays, and swap two variables with `[$a, $b] = [$b, $a];`. One pattern cannot mix keyed and unkeyed entries, and a missing key yields `null` plus an `E_WARNING` in PHP 8.

code

php · 14 lines
php
<?php
declare(strict_types=1);

// One track point from a hiking-route API: [lat, lng, elevation]
$trackPoint = [46.5580, 7.9812, 2061];

[$lat, $lng] = $trackPoint;          // positional: keys 0 and 1
[, , $elevation] = $trackPoint;      // skip two slots

$start = ['lat' => 46.5580, 'lng' => 7.9812];
['lng' => $lng2, 'lat' => $lat2] = $start;   // keyed, any order

[$lat, $lng] = [$lng, $lat];         // swap
echo "$lat $lng $elevation $lat2", PHP_EOL; // 7.9812 46.558 2061 46.558

go deeper

for a junior

Recall both spellings, [] and list(), the keyed form with =>, skipping with an empty slot and the one-line swap.

for a middle

Explain that positional patterns read keys 0, 1, 2 rather than the first elements, why keyed and unkeyed entries cannot mix, and what a missing key does.

for a senior

Use keyed patterns for external payloads so a shape change fails visibly, and review positional unpacking of associative data as a latent null bug.

for a principal

Decide where arrays stop and typed objects begin: destructuring is fine at the edge, but a shape used across many functions deserves a named class the tooling can check.

## What destructuring is **Destructuring** (also called unpacking) assigns several variables from one array in one statement. You write an array-shaped **pattern** on the left of `=` and an array on the right; each variable in the pattern receives the element at the matching key. PHP has two spellings for the pattern: - `[$lat, $lng] = $point;` — the short square-bracket form, the usual choice in modern code. - `list($lat, $lng) = $point;` — the older `list()` construct. It is not a function, and it behaves exactly the same. The whole assignment expression evaluates to the right-hand array, which is why the old idiom `while ([$a, $b] = nextRow())` works: when the call returns `null`, the loop condition is falsy. ## Positional patterns read keys 0, 1, 2 A pattern without keys is positional, and it is easy to misread. It does **not** take "the first two elements"; it takes the elements whose keys are `0` and `1`: | Right-hand side | `[$lat, $lng] = …` gives | |---|---| | `[46.55, 7.98]` | `$lat = 46.55`, `$lng = 7.98` | | `[1 => 7.98, 0 => 46.55]` | `$lat = 46.55`, `$lng = 7.98` (keys win over order) | | `['lat' => 46.55, 'lng' => 7.98]` | both `null`, plus two `Undefined array key` warnings | So a positional pattern suits **lists**, such as the `[lat, lng]` pairs a hiking-route API returns for each track point, or the result of `explode()`. ## Keyed patterns For associative arrays, name the keys: ```php ['lat' => $lat, 'lng' => $lng] = $point; ``` - Keys can be strings, integers or any expression, such as a constant or a variable. - Order does not matter, and you can pick only the keys you need. - Integer keys let you pick from a list by position: `[2 => $elevation] = $trackPoint;`. Keyed patterns are the self-documenting choice for API payloads: the code says which field goes into which variable. ## Skipping, nesting and swapping 1. **Skip** an element by leaving its slot empty: `[, $lng] = $point;` or `[$lat, , $elevation] = $trackPoint;`. 2. **Nest** patterns to reach into nested arrays: `['start' => [$lat, $lng]] = $route;`. 3. **Swap** two variables without a temporary: `[$a, $b] = [$b, $a];`. The right-hand array is built from the old values first, then unpacked. 4. **Bind by reference** with `&`: after `[$lat, &$lng] = $point;`, writing to `$lng` changes `$point[1]`. ## Rules the compiler enforces Some patterns are rejected before the script runs: - **Mixing keyed and unkeyed entries** in one pattern, as in `[$id, 'name' => $name] = $row;`, is a fatal compile error: "Cannot mix keyed and unkeyed array entries in assignments". Nested patterns may each choose their own style. - **A pattern with no variables at all**, only empty slots such as `list(, ,) = $point;`, fails with "Cannot use empty list". - **A rest element** such as `[$head, ...$tail] = $items;` fails with "Spread operator is not supported in assignments"; the spread operator only works when *building* arrays. ## What happens when the data does not fit In PHP 8 a key missing from the right-hand array raises an `E_WARNING` ("Undefined array key") and assigns `null`; before PHP 8.0 it was an `E_NOTICE`. The code keeps running with `null` in the variable, so a pattern that does not match the data's shape is a quiet bug rather than a crash. Checking the shape at the boundary, or using keyed patterns against a documented payload, keeps that from spreading. ## Why interviewers ask about it Destructuring shows up in everyday modern PHP: splitting `explode()` results, unpacking pairs returned from a helper, iterating over rows. The screening version checks that a candidate knows the syntax; the follow-ups check that they know positional patterns read keys `0`, `1`, `2`, and that a mismatch yields `null` rather than an exception. ## Choosing a style - Positional `[$a, $b]` for true lists whose order is the contract: coordinate pairs, `explode()` results, rows fetched as numeric arrays. - Keyed `['lat' => $lat]` for associative data: decoded JSON objects, configuration arrays, database rows fetched by column name. - A small typed object instead, when the same shape travels through many functions and deserves a name.

  • Why does [$lat, $lng] = ['lat' => 46.55, 'lng' => 7.98] leave both variables null?
    A positional pattern reads the keys `0` and `1`, and this array has only the string keys `lat` and `lng`. Each lookup misses, PHP 8 raises an `Undefined array key` warning and assigns `null`. Use a keyed pattern, `['lat' => $lat, 'lng' => $lng] = $point;`, for associative data.
  • Can you destructure an object into variables?
    Only if it implements `ArrayAccess`; the pattern then calls `offsetGet()` for each key. A plain object such as `stdClass` throws an `Error` ("Cannot use object of type stdClass as array"). For ordinary objects, read the properties directly or convert the data to an array first.

saying these in an interview costs you the question

  • A positional pattern takes the first elements whatever their keys
  • list() is a function that returns the unpacked values
  • One pattern can mix keyed and positional entries
  • Swapping two variables with destructuring needs a temporary variable
  • [$head, ...$tail] = $items collects the remaining elements