Arr::mapWithKeys
Rebuilds an array by letting a callback return the key and the value for each item.
public static function mapWithKeys(array $array, callable $callback)Parameters
| Parameter | Type | Description |
|---|---|---|
$$array | array | The source array. A real array is required — the parameter is type hinted, so iterables are rejected. |
$$callback | callable | Receives ($value, $key) and must return an array of key => value pairs to merge into the result. |
Return value
arrayA new array assembled from every key/value pair each callback return produced.
Errors
Raises a TypeError if $array is not an array; emits a warning and contributes nothing if the callback returns a non-iterable value.
Arr::mapWithKeys is the tool for reshaping a list of records into a keyed lookup. The callback receives each value and key, and returns a small associative array; every pair in that return is merged into the result, in iteration order.
When to reach for it
- Turning rows into an
id => roworemail => namemap so later lookups are O(1) instead of a nested loop. - Renaming or prefixing keys across a config or payload array in one pass.
- Producing a
value => labelarray for a select box from database-shaped data.
What trips people up
The callback has to return an array. Returning the value alone is the single most common mistake: PHP will warn about iterating a non-array and the item is silently dropped from the result, leaving you with fewer entries than you started with.
The documentation describes returning one pair, but the implementation loops over whatever you return, so multiple pairs per item work fine and are a legitimate way to expand an array.
Duplicate keys overwrite, last write wins — so a result shorter than the input usually means your key expression is not unique. Keys are also subject to PHP's array-key rules: a numeric string like '07' stays a string, but '7' becomes the integer 7.
Example
When to use it
- Key a list of user rows by email so a later lookup is a single array access.
- Prefix every key in a settings array before merging it into another config.
- Build a value => label array for a form select from record data.
Frequently asked questions
Why does Arr::mapWithKeys return fewer items than I passed in?
Either your key expression produced duplicates and later items overwrote earlier ones, or the callback returned something that is not an array and those items were skipped. Check that the key you build is unique per row.
What is the difference between Arr::mapWithKeys and array_combine?
Arr::mapWithKeys derives the key and the value from the same item in one pass, while array_combine needs two pre-built arrays of matching length. Use mapWithKeys when the key comes from a field inside each record.
Can the callback return more than one key/value pair?
Yes. The implementation iterates over whatever array you return, so returning several pairs expands the result — a supported way to fan one record out into multiple entries.
More examples
Returning more than one pair per item
Four entries out of two input items. The output is larger than the input because each callback return contributed two pairs, which the docs' "single key/value pair" wording does not forbid.
<?php
use Illuminate\Support\Arr;
$users = [
['id' => 1, 'name' => 'Taylor'],
['id' => 2, 'name' => 'Abigail'],
];
// The implementation loops over the returned array, so two pairs per item works.
$expanded = Arr::mapWithKeys($users, function (array $user) {
return [
"user.{$user['id']}.name" => $user['name'],
"user.{$user['id']}.slug" => strtolower($user['name']),
];
});
print_r($expanded);
/*
Array
(
[user.1.name] => Taylor
[user.1.slug] => taylor
[user.2.name] => Abigail
[user.2.slug] => abigail
)
*/Duplicate keys collapse the result
Three orders in, two out: the second 'acme' row overwrote the first. Whenever the result is shorter than the input, the key expression is not unique.
<?php
use Illuminate\Support\Arr;
$orders = [
['ref' => 'A-1', 'customer' => 'acme', 'total' => 100],
['ref' => 'A-2', 'customer' => 'acme', 'total' => 250],
['ref' => 'A-3', 'customer' => 'globex', 'total' => 75],
];
// Keying by a non-unique column silently loses rows.
$byCustomer = Arr::mapWithKeys($orders, fn (array $o) => [$o['customer'] => $o['total']]);
print_r($byCustomer);
// Key by the unique column instead.
$byRef = Arr::mapWithKeys($orders, fn (array $o) => [$o['ref'] => $o['total']]);
echo count($byRef), PHP_EOL;
/*
Array
(
[acme] => 250
[globex] => 75
)
3
*/
Discussion