Multidimensional Arrays
An array element can itself be an array. That's how PHP represents tables of rows, grids, nested configuration and decoded JSON. This lesson shows how to build, read, loop over and transform nested arrays — skills you'll use every time you work with database results or API data.
A list of records
The most common shape in PHP applications is a list of associative arrays — exactly what a database query returns:
<?php $employees = [ ["name" => "Iris", "dept" => "Sales", "salary" => 52000], ["name" => "Omar", "dept" => "IT", "salary" => 61000], ["name" => "Lena", "dept" => "Sales", "salary" => 48000], ]; echo $employees[1]["name"], "\n"; echo count($employees), " employees\n"; foreach ($employees as $e) { printf("%-5s %-6s %8s\n", $e["name"], $e["dept"], number_format($e["salary"])); }
Omar 3 employees Iris Sales 52,000 Omar IT 61,000 Lena Sales 48,000
Chain the brackets to go deeper: $employees[1]["name"] is "element 1, then its name key".
Grids
A grid is a list of rows, each a list of cells:
<?php $board = [ ['X', 'O', 'X'], ['O', 'X', 'O'], [' ', ' ', 'X'], ]; foreach ($board as $r => $row) { echo ' ', implode(' | ', $row), "\n"; if ($r < 2) { echo "---+---+---\n"; } } $diagonal = [$board[0][0], $board[1][1], $board[2][2]]; echo count(array_unique($diagonal)) === 1 ? "Winner: {$diagonal[0]}\n" : "No diagonal win\n";
X | O | X ---+---+--- O | X | O ---+---+--- | | X Winner: X
Modifying nested elements
Assign through the full path. Missing levels are created automatically:
<?php $config = ["db" => ["host" => "localhost", "port" => 3306]]; $config["db"]["port"] = 3307; $config["cache"]["driver"] = "redis"; // creates "cache" $config["cache"]["servers"][] = "10.0.0.5"; // creates "servers" and appends print_r($config);
Array
(
[db] => Array
(
[host] => localhost
[port] => 3307
)
[cache] => Array
(
[driver] => redis
[servers] => Array
(
[0] => 10.0.0.5
)
)
)To change rows while looping, use the key ($rows[$i]['x'] = …), or array_map to produce new rows.
Reading safely
With nested data from outside (JSON, forms), any level might be missing. ?? works through the whole chain without warnings:
<?php $response = ["user" => ["profile" => ["city" => "Porto"]]]; echo $response["user"]["profile"]["city"] ?? "unknown", "\n"; echo $response["user"]["address"]["street"] ?? "unknown", "\n"; echo $response["order"][0]["id"] ?? "no orders", "\n";
Porto unknown no orders
Summarising a table
Group and total rows with a loop, or combine array_column, array_filter and friends:
<?php $sales = [ ["region" => "North", "product" => "Widget", "units" => 12, "price" => 2.5], ["region" => "South", "product" => "Gadget", "units" => 4, "price" => 10.0], ["region" => "North", "product" => "Gadget", "units" => 7, "price" => 10.0], ["region" => "East", "product" => "Widget", "units" => 20, "price" => 2.5], ]; $byRegion = []; foreach ($sales as $row) { $byRegion[$row["region"]] = ($byRegion[$row["region"]] ?? 0) + $row["units"] * $row["price"]; } ksort($byRegion); foreach ($byRegion as $region => $revenue) { printf("%-6s %7.2f\n", $region, $revenue); } $widgetUnits = array_sum(array_column(array_filter($sales, fn($r) => $r["product"] === "Widget"), "units")); echo "Widgets sold: $widgetUnits\n";
East 50.00 North 100.00 South 40.00 Widgets sold: 32
Rows to columns and back
Passing null as the callback to array_map with several arrays "zips" them — which also transposes a matrix:
<?php $matrix = [ [1, 2, 3], [4, 5, 6], ]; $transposed = array_map(null, ...$matrix); foreach ($transposed as $row) { echo implode(" ", $row), "\n"; }
1 4 2 5 3 6
Walking nested data recursively
For structures of unknown depth, array_walk_recursive visits every leaf value. A recursive function (lesson 32) gives you full control:
<?php $menu = [ "Home" => [], "Products" => ["Laptops" => [], "Phones" => ["Android" => [], "iPhone" => []]], "About" => [], ]; function printMenu(array $items, int $depth = 0): void { foreach ($items as $label => $children) { echo str_repeat(" ", $depth), "- $label\n"; printMenu($children, $depth + 1); } } printMenu($menu); $prices = ["a" => 1.5, "b" => ["c" => 2.0, "d" => ["e" => 3.5]]]; $total = 0; array_walk_recursive($prices, function ($value) use (&$total) { $total += $value; }); echo "Total: $total\n";
- Home
- Products
- Laptops
- Phones
- Android
- iPhone
- About
Total: 7Displaying nested data
print_r and var_dump show nested arrays, but for large structures json_encode with pretty printing is often easier to read:
<?php $order = ["id" => 1001, "items" => [["sku" => "A1", "qty" => 2], ["sku" => "B7", "qty" => 1]]]; echo json_encode($order, JSON_PRETTY_PRINT), "\n";
{
"id": 1001,
"items": [
{
"sku": "A1",
"qty": 2
},
{
"sku": "B7",
"qty": 1
}
]
}Try it yourself
Print a class timetable from a nested array: days as keys, each with a list of lessons.
Mon Maths, Physics, PE Tue English, PHP Wed PHP, Maths, Art, History Most frequent: Maths (2 times)