Understanding PHP Multidimensional Arrays
PHP is a powerful scripting language that provides a rich set of functions to handle arrays and other data structures. One of the key strengths of PHP is the
A multidimensional array in PHP is an array whose elements are themselves arrays. Where a regular (indexed or associative) array maps each key to a single value, a multidimensional array maps each key to a whole nested array — letting you model rows-and-columns data, grids, trees, and grouped records.
This chapter covers how to create two-dimensional and deeper arrays, how to read and update individual cells, how to loop over them with foreach, and the most common functions for transforming them. It also points out the gotchas that trip people up when they move from flat arrays to nested ones.
What is a Multidimensional Array?
An array becomes multidimensional the moment one of its values is another array. The dimension (or depth) is how many index operations you need to reach a scalar value:
$a[0]reaches a value → one-dimensional$a[0][1]reaches a value → two-dimensional$a[0][1][2]reaches a value → three-dimensional, and so on.
A two-dimensional array is often pictured as a table: the outer array holds rows, and each inner array holds that row's columns. That mental model is useful, but remember PHP arrays are ordered maps, not rigid grids — rows can have different lengths and the keys can be strings instead of 0, 1, 2. There is no fixed limit on depth, though deeply nested data usually signals you'd be better off with objects or a database.
Creating a Multidimensional Array
The most common way is to nest array literals. Each inner array is one element of the outer array.
A 2D array of strings (a grid)
$grid = [
["value1", "value2", "value3"],
["value4", "value5", "value6"],
["value7", "value8", "value9"],
];In real code the inner arrays are usually associative, so each row reads like a record:
A list of records
$employees = [
["name" => "Ann", "title" => "Engineer", "salary" => 65000],
["name" => "Bob", "title" => "Designer", "salary" => 58000],
["name" => "Cara", "title" => "Manager", "salary" => 72000],
];You can also build one up incrementally, which is handy when the data comes from a loop or a database query:
$matrix = [];
$matrix[0][0] = 1;
$matrix[0][1] = 2;
$matrix[1][0] = 3;
$matrix[1][1] = 4;
// $matrix is now [[1, 2], [3, 4]]Accessing Elements
Add one set of brackets per dimension. The first index selects the outer element (the row); the second selects the inner element (the column):
echo $grid[1][2]; // "value6" — row 1, column 2
echo $employees[2]["name"]; // "Cara"PHP is zero-indexed, so the second row is [1] and the third column is [2]. Reading a key that doesn't exist raises a warning and yields null; use isset() or the null-coalescing operator to stay safe:
$salary = $employees[5]["salary"] ?? 0; // no warning if the row is missingLooping Over a Multidimensional Array
Nested foreach loops are the idiomatic way to walk a 2D array — the outer loop visits each row, the inner loop visits that row's values:
$employees = [
["name" => "Ann", "salary" => 65000],
["name" => "Bob", "salary" => 58000],
];
foreach ($employees as $row) {
foreach ($row as $key => $value) {
echo "$key: $value\n";
}
echo "---\n";
}For tabular records it's often cleaner to destructure the inner keys directly:
foreach ($employees as $emp) {
echo "{$emp['name']} earns {$emp['salary']}\n";
}
// Ann earns 65000
// Bob earns 58000Modifying Elements
Assign through the full index path to update a single cell, and append a new row with [] or array_push():
$employees[0]["salary"] = 70000; // update one field
$employees[] = ["name" => "Dan", "salary" => 60000]; // add a row
array_pop($employees); // remove the last rowarray_pop() removes and returns the last row, so the two operations above cancel out.
Transforming with array_map and array_column
array_map() applies a callback to every element. To transform every cell, map an inner array_map over each row:
Uppercase every value in a 2D array
$grid = [["a", "b"], ["c", "d"]];
$upper = array_map(function ($row) {
return array_map("strtoupper", $row);
}, $grid);
// $upper is [["A", "B"], ["C", "D"]]When the inner arrays are records, array_column() pulls a single field out of every row into a flat array — perfect for extracting one column:
$employees = [
["name" => "Ann", "salary" => 65000],
["name" => "Bob", "salary" => 58000],
];
$names = array_column($employees, "name"); // ["Ann", "Bob"]
$total = array_sum(array_column($employees, "salary")); // 123000Common Gotchas
- Off-by-one indices.
$grid[1][2]is the second row, third column — both indices are zero-based. - Mixing up the index order.
$employees[0]["name"]works;$employees["name"][0]does not, because the outer array is keyed by integers. - Undefined keys. Accessing a missing row or column emits a warning and returns
null. Guard withisset()or?? default. - Functions that need recursion. Plain
count($arr)counts only the top level — usecount($arr, COUNT_RECURSIVE). To walk every leaf, usearray_walk_recursive()instead ofarray_walk(). - Copy semantics. PHP arrays are copied by value, so
$copy = $original;followed by editing$copy[0][0]does not change$original— unlike object references.
Conclusion
Multidimensional arrays let you represent tables, grids, and grouped records by nesting one array inside another. Read and write individual cells with chained [] indices, iterate with nested foreach loops, and reshape data with array_map(), array_column(), and the recursive array functions. For a broader tour of PHP's array toolkit, see PHP Arrays.