PHPMultidimensional Arrays

Multidimensional Arrays

A multidimensional array is simply an array whose values are themselves arrays. PHP does not have a separate "2D array" or "matrix" type - nesting is just the natural consequence of arrays being able to hold any value, including other arrays. This is how you represent anything with structure: a spreadsheet-like table, a list of records pulled from a database, or a tree of configuration settings.

Arrays of arrays

The simplest case is an indexed array where each element is itself an indexed array - useful for grid-like data such as rows and columns.

A simple grid

PHP
<?php
$grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
];

echo $grid[1][2]; // 6 - row index 1, column index 2
6
Nested associative structures

The far more common real-world shape is a list of associative arrays - each element is a "record" with named fields. This is exactly what you get back from a database query or a decoded JSON API response, which makes it worth practicing directly.

A list of user records

PHP
<?php
$users = [
    ["id" => 1, "name" => "Omar", "role" => "admin"],
    ["id" => 2, "name" => "Lucia", "role" => "editor"],
    ["id" => 3, "name" => "Femi", "role" => "viewer"],
];

echo $users[0]["name"]; // Omar
echo "\n";
echo $users[2]["role"]; // viewer
Omar
viewer
Accessing and modifying nested values

You chain bracket access to reach into deeper levels, and the same chaining works for writing, not just reading. If an intermediate key does not exist yet, assigning to a deep path will create the missing arrays automatically - a convenience, but also something to be careful with, since a typo in a key silently creates a new branch instead of raising an error.

Reading and writing nested values

PHP
<?php
$users = [
    ["id" => 1, "name" => "Omar", "role" => "admin"],
    ["id" => 2, "name" => "Lucia", "role" => "editor"],
];

$users[1]["role"] = "admin"; // promote Lucia
$users[0]["settings"]["theme"] = "dark"; // creates "settings" automatically

print_r($users[1]);
print_r($users[0]);
Array
(
    [id] => 2
    [name] => Lucia
    [role] => admin
)
Array
(
    [id] => 1
    [name] => Omar
    [role] => admin
    [settings] => Array
        (
            [theme] => dark
        )

)
Auto-vivification hides typos
Writing `$users[0]["setings"]["theme"] = "dark";` (note the misspelled key) does not raise an error - PHP happily creates a brand-new nested array under the misspelled key. When debugging a "missing" nested value, check for typos in every level of the key chain before assuming the data itself is wrong.
Pulling one column out with array_column()

A frequent task is extracting a single field from every record in a list - for example, getting just the names out of a list of user records. array_column() does this in one call, and can optionally re-index the result by another field.

Extracting one field from every record

PHP
<?php
$users = [
    ["id" => 1, "name" => "Omar", "role" => "admin"],
    ["id" => 2, "name" => "Lucia", "role" => "editor"],
    ["id" => 3, "name" => "Femi", "role" => "viewer"],
];

$names = array_column($users, "name");
print_r($names);

// Re-index the result by "id" instead of 0, 1, 2...
$byId = array_column($users, "name", "id");
print_r($byId);
Array
(
    [0] => Omar
    [1] => Lucia
    [2] => Femi
)
Array
(
    [1] => Omar
    [2] => Lucia
    [3] => Femi
)
  • There is no fixed depth limit for nesting, but two or three levels is usually the practical ceiling before the code becomes hard to follow.

  • Looping over nested structures usually means a nested foreach - an outer loop over records, an inner loop (or direct key access) for fields.

  • array_column() works on arrays of arrays or arrays of objects, which makes it handy after decoding a JSON API response with json_decode($json, true).

  • Passing null as the second argument to array_column() returns whole rows, re-indexed by the key you name in the third argument.

Deep copies, not references
Assigning one array to another variable (`$copy = $original;`) copies the array by value, including nested arrays. Changing `$copy` will not affect `$original`. This differs from objects, which are always assigned by reference/handle in PHP.
Tip
When a nested structure starts needing more than two or three levels, or the same shape shows up in many places, consider modeling it as a class instead of a deeply nested array - it becomes far easier to validate and to catch typos at development time.