Nested arrays
A hook in the cloakroom can hold not only a coat but a bag too, and the bag has its own tagged pockets. To get the gloves out, you first find the hook and then the right pocket.
Arrays work the same way: the value of an element can be another array. An array that lies inside another array is called a nested array. This is how you store, for example, a list of users where each one has a name and an age:
<?php
$users = [
['name' => 'Anna', 'age' => 31],
['name' => 'Boris', 'age' => 25],
];
echo $users[1]['name'], "\n"; // Boris
$users[0]['age'] = 32;
$users[] = ['name' => 'Vera', 'age' => 19];
echo count($users), ' ', $users[0]['age'], "\n"; // 3 32Let's go through it line by line:
$usersis a list, and each of its elements is the card of one user: an associative array with the keys'name'and'age'.$users[1]['name']is read in steps:$users[1]is Boris's card, and['name']takes the name from it. It printsBoris.$users[0]['age'] = 32;follows the same path and changes the age right inside Anna's card.$users[] = ['name' => 'Vera', 'age' => 19];adds a whole new card to the end of the list.count($users)counts the cards, there are3, and Anna's age is now32.
A long array is handy to write over several lines, one element per line. A comma after the last element is allowed: that way a new line can be added without touching the previous one.
Two kinds of nesting
A list of cards
In $users the first index is the card's number, the second is a field inside it: $users[0]['name']. This shape is used when there is a lot of data of one kind, all with the same fields: users, products, orders.
A card with a list inside
It can be the other way round too: in an associative array, one of the fields is a list. print_r helps you look inside such an array: it prints a nested array with an extra indent.
$order = ['id' => 7, 'items' => ['tea', 'cake']];
$order['items'][] = 'juice';
print_r($order);
// Array
// (
// [id] => 7
// [items] => Array
// (
// [0] => tea
// [1] => cake
// [2] => juice
// )
//
// )Here the first key is a field of the order, the second a number in the list: $order['items'][2] gives 'juice'. The line $order['items'][] = 'juice' adds an element to the nested list the same way $a[] = … adds one to an ordinary list.
Walking with two loops
To visit every field of every card, you need two foreach loops: the outer one goes over the cards, the inner one over a card's pairs. As in the multiplication table from the loops theme, the line is built with .=:
foreach ($users as $user) {
$line = '';
foreach ($user as $field => $value) {
$line .= $field . '=' . $value . ' ';
}
echo $line, "\n";
}
// name=Anna age=32
// name=Boris age=25
// name=Vera age=19Let's go through the steps:
- The outer loop puts a copy of the next card into
$user. $line = ''starts a new line for each card.- The inner loop goes over the card's pairs and appends the key, the
=sign and the value to$line. - After the inner loop,
echoprints the finished line, and the outer loop takes the next card.
Here the bag picture falls short: in a real cloakroom, people rarely put a bag inside a bag. Arrays, though, nest inside each other to any depth—for example, each user can have a list of orders, and each order a list of products.
Common mistake
A field is read straight from the list, without picking a card first:
echo $users['name'], "\n"; // ✗Warning: Undefined array key "name"The keys in $users are the card numbers 0, 1 and 2, while the key 'name' exists only inside each card. PHP gives a warning and prints an empty line. Pick the card first, then the field: $users[0]['name'].
Key points
- The value of an element can be another array;
$users[1]['name']is read in steps: first the card, then the field. - A write along such a path,
$users[0]['age'] = 32, changes the value inside the nested array. - A nested array is walked with two
foreachloops: the outer one over the cards, the inner one over their fields. print_rshows a nested array with indents, and reading a field without picking a card givesWarning: Undefined array key.