Signature
array_replace_recursive(array $array, array ...$replacements): arrayPurpose
array_replace_recursive() lays one or more arrays on top of a base array and returns the combined result. Matching keys take their value from the later array. Keys that exist only in the later array are added. Keys that exist only in the base array stay as they were. The "recursive" part means that when both sides hold an array under the same key, PHP does not swap the whole inner array. It repeats the same process inside it.
The typical use is layered configuration: a full set of defaults, with a small override array that changes only a few deep settings.
Signature
Parameters and defaults
$array: the base array. Its values are the ones that get replaced....$replacements: zero or more arrays applied in order from left to right. When two replacement arrays touch the same key, the later one wins.
There are no default values. If you pass only the base array, you get back an array with the same contents.
Return value and failure cases
The function returns a new array. The arrays you passed in are not modified, because arrays are passed by value. Every argument must be an array. Passing something else, such as null or a string, throws a TypeError, so check optional configuration before the call.
The merge rule
For each key in a replacement array:
- If the base value and the replacement value are both arrays, the function recurses into them.
- Otherwise the replacement value wins. A scalar can replace an array, and an array can replace a scalar.
- If the key is missing in the base, it is created.
Example 1: overriding nested configuration
Only the port changes inside db. The host survives because the inner arrays are merged rather than swapped.
$defaults = [
'db' => ['host' => 'localhost', 'port' => 3306],
'debug' => false,
];
$overrides = [
'db' => ['port' => 3307],
'debug' => true,
];
echo json_encode(array_replace_recursive($defaults, $overrides), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"db":{"host":"localhost","port":3307},"debug":true}
Example 2: comparison with array_replace()
Both functions replace by key. Plain array_replace() swaps the entire inner list, while the recursive version replaces only index 0 and keeps the remaining elements.
$base = ['berries' => ['blackberry', 'raspberry', 'cranberry']];
$new = ['berries' => ['blueberry']];
echo json_encode(array_replace_recursive($base, $new), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(array_replace($base, $new), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"berries":["blueberry","raspberry","cranberry"]}
{"berries":["blueberry"]}
Example 3: several replacements and type changes
The first replacement turns a into a string and b into an array. The second replacement then puts an array back over the string in a. Under c, an empty replacement array has nothing to contribute, so the original list is kept.
$base = ['a' => ['x' => 1, 'y' => 2], 'b' => 'text', 'c' => [1, 2]];
$r1 = ['a' => 'flat', 'b' => ['now' => 'array']];
$r2 = ['a' => ['z' => 3], 'c' => []];
echo json_encode(array_replace_recursive($base, $r1, $r2), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"a":{"z":3},"b":{"now":"array"},"c":[1,2]}
Edge cases
- Integer keys are matched, not appended. The list
['a', 'b']is treated as keys0and1. A replacement list['z']overwrites key0and leaves key1alone. Lists are never concatenated. - Numeric string keys such as
"5"become integer keys, as they do in any PHP array, so they match integer keys. - An empty replacement array inside a nested position changes nothing. You cannot use it to clear an inner array. To clear a value, replace it with a non-array value such as
null, and then handle that value yourself. - Order matters.
array_replace_recursive($a, $b)andarray_replace_recursive($b, $a)give different results whenever the arrays share keys. - Mixed types are allowed. Whenever one side is not an array, the replacement value simply wins, whatever its type.
Common mistakes
- Expecting list concatenation. If you want to append items, this is the wrong tool.
array_merge_recursive()combines differently, and it renumbers integer keys and gathers duplicate string keys into arrays. - Expecting renumbering. Integer keys keep their identity, so sparse keys stay sparse.
- Passing
nullas an override. A missing configuration source must become[]before the call, for example with$extra ?? []. - Assuming arrays can be removed. The function adds and overwrites keys. It never deletes them.
- Choosing it when a shallow replacement is intended. If the whole inner array should be swapped, use
array_replace()or the+operator instead.
Related functions
array_replace()replaces by key at the top level only.array_merge_recursive()merges recursively, with different rules for keys.array_merge()merges at the top level, renumbering integer keys.
Recap
array_replace_recursive() overlays arrays from left to right, key by key, descending wherever both values are arrays. Anything else is decided by the later value. It returns a new array, never removes keys, treats integer keys by position, and throws a TypeError for non-array arguments.
Tested examples
$defaults = [
'db' => ['host' => 'localhost', 'port' => 3306],
'debug' => false,
];
$overrides = [
'db' => ['port' => 3307],
'debug' => true,
];
echo json_encode(array_replace_recursive($defaults, $overrides), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"db":{"host":"localhost","port":3307},"debug":true}
$base = ['berries' => ['blackberry', 'raspberry', 'cranberry']];
$new = ['berries' => ['blueberry']];
echo json_encode(array_replace_recursive($base, $new), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(array_replace($base, $new), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"berries":["blueberry","raspberry","cranberry"]}
{"berries":["blueberry"]}
$base = ['a' => ['x' => 1, 'y' => 2], 'b' => 'text', 'c' => [1, 2]];
$r1 = ['a' => 'flat', 'b' => ['now' => 'array']];
$r2 = ['a' => ['z' => 3], 'c' => []];
echo json_encode(array_replace_recursive($base, $r1, $r2), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"a":{"z":3},"b":{"now":"array"},"c":[1,2]}