Lesson 56 of 100
Arrays15 min5 checksPHP 8.5

Group Records by a Shared Key

Learn how to turn a flat list of associative arrays into stable groups keyed by a shared field, using a plain foreach loop and PHP's array key rules.

01 · THE IDEAREAD → TRY → LEARN

Why group records?

Data often arrives as a flat list: orders, students, log entries. Each item is an associative array, and several items share a value such as a status, a team or a category. Reports usually need those items collected together. Turning a flat list into groups is one of the most common array transformations in everyday PHP.

The tool for the job is the PHP array itself. An array is an ordered map, so it can use the shared value as a key and keep a list of matching records as the value. Because the map is ordered, groups appear in the order in which each key was first inserted. That order is what makes the result stable and predictable.

The core pattern

The idea has three steps. Start with an empty $groups array. Loop over the records. For each record, append it to the list stored under its group key. The append syntax $groups[$key][] = $item does the work: if $groups[$key] does not exist yet, PHP creates an empty array there and then appends the item.

Here is a small worked example that groups order IDs by status:

Example
<?php
$orders = [
    ['id' => 1, 'status' => 'paid'],
    ['id' => 2, 'status' => 'new'],
    ['id' => 3, 'status' => 'paid'],
];

$groups = [];
foreach ($orders as $order) {
    $groups[$order['status']][] = $order['id'];
}

echo json_encode($groups, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"paid":[1,3],"new":[2]}

The key paid is inserted first, so it comes first in the result. Inside each group the IDs keep their original order, because each one is appended after the previous.

Keys are converted

Group values become array keys, so the key rules from the manual apply. A string holding a valid decimal integer, such as "8", is stored as the integer 8. A string such as "08" or "+8" is not a valid canonical integer and stays a string. Booleans and null are converted too, and arrays or objects cannot be keys at all. For grouping, the safest choice is to use strings or integers as group values.

Example
<?php
$groups = [];
foreach (['8', '08', '+8'] as $label) {
    $groups[$label][] = $label;
}

echo json_encode(array_keys($groups), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
[8,"08","+8"]

The first key comes back as an integer, while the other two stay strings. Watch for this if you later compare keys with strict equality.

Records that lack the key

Reading a key that does not exist produces a warning and yields null, and null would then be used as the key "". That quietly creates a bogus group. A robust grouping function checks first. Use array_key_exists, not isset, when the key is present but its value may be null. The function isset returns false for a null value, while array_key_exists only asks whether the key is there.

Example
<?php
$record = ['team' => null];

echo json_encode(
    [isset($record['team']), array_key_exists('team', $record)],
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);
Output
[false,true]

In this lesson, a record without the requested key is skipped. Other designs are valid, such as placing those records in an unknown group. Whichever you pick, decide it on purpose and test it.

Design checklist

  • Create $groups as an empty array before the loop, so an empty input returns an empty array.
  • Append with []; do not assign with = or you will overwrite earlier records.
  • Read the group key from each record only after confirming it exists.
  • Return the whole record, so callers lose no information.
  • Do not sort unless asked. First-seen order is already deterministic.

Your exercise

Write groupByKey(array $records, string $key): array. It receives a list of associative arrays and the name of the field to group by. It returns an array whose keys are the distinct values found in that field, in first-seen order. Each value is the list of full records that share the key, in their original order. Records that do not contain the field are skipped. An empty input returns an empty array. You may assume group values are strings.

The tests compare the returned values, not printed output, so use return and do not echo anything. Start with the loop pattern above, add the guard, and check each of the five cases mentally before you run them.

Before you start

Functions · Arrays · Types

You’ll practice
  • Build stable grouped record collections with a loop
  • Implement and test a deterministic PHP 8.4 function
Your task

Make groupByKey() 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.