Array merge recursive: примеры (PHP)

Функция array_merge_recursive в PHP: полный обзор с примерами кода
Раздел: Работа с массивами
array_merge_recursive(array ...$arrays): array

Основные сведения о array_merge_recursive

Назначение функции

Функция array_merge_recursive в PHP выполняет рекурсивное слияние нескольких массивов. Она используется в случаях, когда требуется объединить массивы, содержащие одинаковые строковые ключи, без потери данных. В отличие от array_merge, при обнаружении одинаковых строковых ключей значения объединяются в массив, а не перезаписываются.

Аргументы функции

Синтаксис: array_merge_recursive(array ...$arrays): array

Функция принимает переменное количество аргументов:

  • ...$arrays – один или более массивов для рекурсивного слияния. Минимум один массив должен быть передан.

Базовые примеры использования

Слияние массивов с одинаковыми строковыми ключами
$arr1 = ['color' => 'red', 'size' => 'M'];
$arr2 = ['color' => 'blue', 'weight' => 100];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[color] => Array
(
[0] => red
[1] => blue
)

[size] => M
[weight] => 100
)
Рекурсивное слияние многомерных массивов
$arr1 = ['data' => ['id' => 1, 'values' => [1, 2]]];
$arr2 = ['data' => ['id' => 2, 'values' => [3, 4]]];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[data] => Array
(
[id] => Array
(
[0] => 1
[1] => 2
)

[values] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)

)

)
Обработка числовых ключей
$arr1 = [1 => 'a', 2 => 'b'];
$arr2 = [3 => 'c', 4 => 'd'];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
)

Похожие функции в PHP

Функция array_merge выполняет нерекурсивное слияние массивов. При совпадении строковых ключей значение из последнего массива перезаписывает предыдущее. Числовые ключи переиндексируются.

array_replace_recursive

Функция array_replace_recursive заменяет элементы массива элементами других переданных массивов рекурсивно. При совпадении ключей значение из последнего массива заменяет предыдущее, в отличие от array_merge_recursive, которая создает массив значений.

Выбор функции

array_merge_recursive применяется, когда нужно сохранить все значения из всех массивов по одинаковым ключам. array_merge используется для простого объединения с приоритетом последних значений. array_replace_recursive подходит для рекурсивного замещения значений.

Распространенные ошибки

Непредвиденное создание массивов

Частой ошибкой является непонимание того, что функция всегда создает массив для одинаковых строковых ключей, даже если значения скалярные.

$arr1 = ['id' => 1];
$arr2 = ['id' => 2];
$result = array_merge_recursive($arr1, $arr2);
var_dump($result['id']);
array(2) {
[0]=> int(1)
[1]=> int(2)
}
Потеря ассоциативных ключей во внутренних массивах

При слиянии внутренних массивов с числовыми ключами происходит их переиндексация.

$arr1 = ['items' => [10 => 'apple']];
$arr2 = ['items' => [20 => 'banana']];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[items] => Array
(
[0] => apple
[1] => banana
)

)
Слияние разных типов данных

Если в одинаковых ключах содержатся разные типы данных (массив и скаляр), результат может быть неочевидным.

$arr1 = ['data' => 'string'];
$arr2 = ['data' => ['array']];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[data] => Array
(
[0] => string
[1] => array
)

)

Изменения в последних версиях PHP

PHP 8.0

В PHP 8.0 функция array_merge_recursive не претерпела значительных изменений в поведении. Однако, как и многие другие функции, она стала строже относиться к типам передаваемых аргументов. Передача не массива теперь вызывает TypeError.

array_merge_recursive([], 'not_array');
TypeError: array_merge_recursive(): Argument #2 must be of type array, string given
Исторические изменения

До PHP 7.4 функция корректно обрабатывала только массивы и скаляры. Сейчас она также работает с объектами, реализующими интерфейс Traversable, но они преобразуются в массивы.

Расширенные примеры применения

Слияние более двух массивов
Пример php
$arr1 = ['a' => 1, 'b' => 2];
$arr2 = ['a' => 3, 'c' => 4];
$arr3 = ['a' => 5, 'd' => 6];
$result = array_merge_recursive($arr1, $arr2, $arr3);
print_r($result);
Array
(
[a] => Array
(
[0] => 1
[1] => 3
[2] => 5
)

[b] => 2
[c] => 4
[d] => 6
)
Глубокое рекурсивное слияние сложных структур
Пример php
$arr1 = [
'database' => [
'host' => 'localhost',
'port' => 3306,
'options' => ['charset' => 'utf8']
]
];
$arr2 = [
'database' => [
'host' => '127.0.0.1',
'options' => ['collation' => 'utf8_general_ci']
],
'debug' => true
];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[database] => Array
(
[host] => Array
(
[0] => localhost
[1] => 127.0.0.1
)

[port] => 3306
[options] => Array
(
[charset] => utf8
[collation] => utf8_general_ci
)

)

[debug] => 1
)
Обработка массивов с числовыми и строковыми ключами
Пример php
$arr1 = [0 => 'zero', 'key' => 'value1', 2 => 'two'];
$arr2 = [0 => 'ZERO', 'key' => 'value2', 3 => 'three'];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[0] => zero
[key] => Array
(
[0] => value1
[1] => value2
)

[1] => two
[2] => ZERO
[3] => three
)
Слияние с сохранением структуры объектов в виде массивов
Пример php
$obj1 = (object)['prop' => 'val1'];
$obj2 = (object)['prop' => 'val2'];
$arr1 = ['object' => $obj1];
$arr2 = ['object' => $obj2];
$result = array_merge_recursive($arr1, $arr2);
print_r($result);
Array
(
[object] => Array
(
[0] => stdClass Object
(
[prop] => val1
)

[1] => stdClass Object
(
[prop] => val2
)

)

)

Аналоги в других языках программирования

JavaScript: пользовательская реализация

В JavaScript отсутствует встроенная функция для рекурсивного слияния массивов с сохранением всех значений. Пример реализации:

function mergeRecursive(target, source) {
for (let key in source) {
if (source[key] instanceof Object && key in target) {
mergeRecursive(target[key], source[key]);
} else if (Array.isArray(target[key]) && Array.isArray(source[key])) {
target[key] = target[key].concat(source[key]);
} else if (target.hasOwnProperty(key)) {
target[key] = [target[key], source[key]];
} else {
target[key] = source[key];
}
}
return target;
}

let obj1 = { color: 'red', size: 'M' };
let obj2 = { color: 'blue', weight: 100 };
console.log(mergeRecursive(obj1, obj2));
{ color: [ 'red', 'blue' ], size: 'M', weight: 100 }
Python: использование словарей

В Python можно использовать метод update с дополнительной логикой или библиотеку deepmerge.

def merge_recursive(dict1, dict2):
for key, value in dict2.items():
if key in dict1 and isinstance(dict1[key], dict) and isinstance(value, dict):
merge_recursive(dict1[key], value)
elif key in dict1:
dict1[key] = [dict1[key], value] if not isinstance(dict1[key], list) else dict1[key] + [value]
else:
dict1[key] = value
return dict1

dict1 = {'color': 'red', 'size': 'M'}
dict2 = {'color': 'blue', 'weight': 100}
print(merge_recursive(dict1, dict2))
{'color': ['red', 'blue'], 'size': 'M', 'weight': 100}
MySQL: работа с JSON

В MySQL для работы с JSON существует функция JSON_MERGE_PATCH (замена) и JSON_MERGE_PRESERVE (сохранение всех значений).

SELECT JSON_MERGE_PRESERVE('{"color": "red"}', '{"color": "blue"}') AS result;
result: {"color": ["red", "blue"]}

PHP array_merge_recursive function comments

En
Array merge recursive Merge two or more arrays recursively