01 · THE IDEAREAD → TRY → LEARN
Why key type matters
A PHP array is an ordered map, and every element has a key that is either an integer or a string. When you combine two arrays, those keys decide what happens to the values. The same-looking operation can overwrite, append, or renumber depending on the key type, so merge code needs to be intentional.
The main tool is array_merge(array ...$arrays): array. It takes any number of arrays and returns a new array. The inputs are not modified. Since PHP 7.4 you can call it with no arguments, and it returns an empty array.
The two rules
- String keys: if the same string key appears in more than one input, the later value wins.
- Numeric keys: values are never overwritten. They are appended in order and renumbered from zero.
The first rule makes array_merge() a good fit for settings, where defaults come first and overrides come second.
$defaults = ['theme' => 'light', 'lang' => 'en'];
$overrides = ['theme' => 'dark'];
echo json_encode(array_merge($defaults, $overrides), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"theme":"dark","lang":"en"}
The theme value from the second array replaced the first one. The lang key was kept because nothing overrode it.
Numeric keys are renumbered
The second rule surprises many people. A numeric key is treated as a position in a list, not as an identity. Two values that share the key 5 are both kept, and the key itself disappears.
echo json_encode(array_merge([], [1 => 'data']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo json_encode(array_merge([5 => 'a'], [5 => 'b']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;["data"] ["a","b"]
Both results are plain lists. If the integer keys meant something, such as database ids, array_merge() throws that information away.
Three ways to combine, three results
PHP offers other ways to combine arrays, and each one handles numeric keys differently:
array_merge($a, $b)appends numeric keys and renumbers them.$a + $bkeeps the first array's value whenever a key exists in both. Keys are preserved.array_replace($a, $b)copies values from later arrays into the first one by key. A later value wins for any matching key, numeric or string.
The next example runs all three on the same input.
$a = [0 => 'zero_a', 2 => 'two_a', 3 => 'three_a'];
$b = [1 => 'one_b', 3 => 'three_b', 4 => 'four_b'];
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(array_merge($a, $b), $flags), PHP_EOL;
echo json_encode($a + $b, $flags), PHP_EOL;
echo json_encode(array_replace($a, $b), $flags), PHP_EOL;["zero_a","two_a","three_a","one_b","three_b","four_b"]
{"0":"zero_a","2":"two_a","3":"three_a","1":"one_b","4":"four_b"}
{"0":"zero_a","2":"two_a","3":"three_b","1":"one_b","4":"four_b"}
The merged result is a clean six-item list. The union keeps three_a, while array_replace() yields three_b. Those last two results are encoded as JSON objects because their integer keys are not a sequence starting at zero.
Choosing the right operation
Ask what the keys mean:
- If the arrays are lists and you want every item, use
array_merge(). - If string keys are settings and the second array should win, use
array_merge()orarray_replace(). - If the first array should win and you want to fill gaps, use
+. - If integer keys are identities that must survive, use
array_replace()or+, notarray_merge().
Edge cases and mistakes
- Merging two empty arrays gives an empty array.
- Argument order matters for string keys. Swapping defaults and overrides silently reverses who wins.
- A numeric-looking string key such as
'7'becomes the integer key7in a PHP array, so it follows the numeric rule. array_merge()is shallow. Nested arrays under a string key are replaced whole, not combined. The relatedarray_merge_recursive()exists for other behavior, but use it carefully.
Exercise contract
Write mergeSettings(array $defaults, array $overrides): array. It returns a new array in which string keys from $overrides replace those in $defaults, new string keys are added, and numeric-keyed values are appended and renumbered. The function must not print anything. It must return the array. The five tests cover overriding, list appending, renumbering a lone numeric key, new keys, and empty input.
Recap
array_merge() overwrites on string keys and appends with renumbering on numeric keys. + keeps the first value, and array_replace() replaces by key. Pick the one that matches what your keys mean.
Functions · Arrays · Types
- Handle numeric and string keys intentionally
- Implement and test a deterministic PHP 8.4 function