Lesson 46 of 100
Arrays15 min5 checksPHP 8.5

Navigate Multidimensional Arrays

Learn to read, update and loop over nested PHP arrays safely, then write a function that totals data across nested order records.

01 · THE IDEAREAD → TRY → LEARN

Arrays inside arrays

A PHP array is an ordered map, and its values can be any type, including other arrays. That is all a multidimensional array is: a value that happens to be an array, holding another value that is an array, and so on. Records from JSON, configuration trees and table rows all take this shape.

You reach a nested value by chaining square brackets, one key per level: $user['address']['city']. Each bracket works on the result of the one before it.

Reading safely

Chained access is fine when the structure is guaranteed. When a key is missing, PHP issues a warning and the result is null. Reading through a missing level is worse, because the next bracket then runs on null.

The null coalescing operator ?? handles this. In $a['x']['y'] ?? 'fallback', PHP checks each step quietly and uses the fallback if any level is missing or null. No warning is raised.

Example
<?php
$user = [
    'name' => 'Ada',
    'address' => ['city' => 'London', 'geo' => ['lat' => 51.5]],
];

echo $user['address']['city'], PHP_EOL;
echo json_encode($user['address']['geo']['lat'] ?? null), PHP_EOL;
echo json_encode($user['address']['geo']['lng'] ?? null), PHP_EOL;
echo json_encode($user['phone']['home'] ?? 'none'), PHP_EOL;
Output
London
51.5
null
"none"

The phone key does not exist at all, yet the last line is safe and prints the fallback. One caveat: ?? also replaces a key that exists but holds null. Use array_key_exists() if you must tell those cases apart.

Updating nested values

Assignment uses the same chain of brackets. You can change a value, use compound operators such as +=, or add new keys. If an intermediate level does not exist, PHP creates it as an array when you assign through it. unset() removes a key at any depth and does not reindex the array.

Example
<?php
$inventory = [
    'north' => ['apples' => 4, 'pears' => 2],
    'south' => ['apples' => 1],
];

$inventory['north']['apples'] += 3;
$inventory['south']['pears'] = 5;
$inventory['east']['plums'] = 9;
unset($inventory['north']['pears']);

echo json_encode($inventory), PHP_EOL;
Output
{"north":{"apples":7},"south":{"apples":1,"pears":5},"east":{"plums":9}}

Notice that east did not exist before the assignment. Creating levels this way is convenient, but a typo in a key will silently create a new branch instead of failing. Be careful with the spelling of keys.

Looping through nested data

Use foreach for each level. Array destructuring lets you pull the fields you need directly into the loop header, which is easier to read than repeated bracket chains.

Example
<?php
$rows = [
    ['id' => 1, 'tags' => ['php', 'array']],
    ['id' => 2, 'tags' => []],
    ['id' => 3, 'tags' => ['json']],
];

$counts = [];
foreach ($rows as ['id' => $id, 'tags' => $tags]) {
    $counts[$id] = count($tags);
}

echo json_encode($counts), PHP_EOL;
Output
{"1":2,"2":0,"3":1}

The result keys start at 1, not 0, so JSON encodes the array as an object. Destructuring a missing key gives null and a warning, so for uncertain data prefer ?? inside the loop body.

If you want to change elements while looping, write back through the key, as in $rows[$i]['seen'] = true inside foreach ($rows as $i => $row). The loop variable holds a copy, so changing $row alone does not alter the original array.

Common mistakes

  • Chaining brackets on data that may be incomplete, instead of using ??.
  • Using ?? when a falsy value such as 0 is valid. ?? only replaces null, so this is actually safe, but ?: would wrongly replace 0.
  • Editing the loop copy instead of the original array.
  • Forgetting that unset() leaves gaps in integer keys.

Exercise contract

Write cityOrderTotal(array $orders, string $city): int. Each order may contain customer.address.city and an items list. Each item may contain price and qty.

  • Only count orders whose city equals $city exactly (case-sensitive).
  • An order with a missing customer, address or city is skipped.
  • A missing items list adds nothing.
  • A missing price counts as 0 and a missing qty counts as 1.
  • Return the sum of price * qty over all matching items.

Recap

Nested arrays are chains of keys. Read them with ?? when the shape is uncertain, write through the full key path, and use foreach with destructuring to walk each level.

Before you start

Functions · Arrays · Types

You’ll practice
  • Read and update nested in-memory records safely
  • Implement and test a deterministic PHP 8.4 function
Your task

Make cityOrderTotal() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.