Функция PHP: array_merge_recursive
Функция array_merge_recursive в PHP объединяет массивы, сохраняя все значения при совпадении строковых ключей.
Функция array_merge_recursive() в PHP объединяет два или более массива в один. Её отличительная особенность — обработка совпадающих строковых ключей: вместо того чтобы позволять более позднему значению перезаписывать более раннее, она объединяет оба значения в подмассив, рекурсивно обходя вложенные массивы. Это делает её подходящим инструментом, когда нужно сохранить каждое значение, а не оставить только значение из последнего массива.
На этой странице рассматриваются синтаксис и параметры, принцип работы рекурсивного слияния, отличия от array_merge(), реальный пример использования и подводные камни, о которых стоит знать.
Синтаксис
array_merge_recursive(array $array1, array ...$arrays): arrayПараметры
array1: Первый входной массив....$arrays: Один или несколько дополнительных массивов для слияния.
Возвращаемое значение
Возвращает результирующий объединённый массив.
Как работает array_merge_recursive?
Функция применяет два разных правила в зависимости от типа ключа:
- Строковые ключи, встречающиеся более чем в одном массиве, объединяются. Если оба значения являются скалярными, они помещаются в новый подмассив; если оба являются массивами, функция рекурсивно обходит их и объединяет на следующем уровне.
- Целочисленные (числовые) ключи никогда не перезаписываются. Каждый элемент с числовым ключом добавляется в конец и перенумеровывается, так что ничего не теряется, а результат переиндексируется начиная с
0.
Вот почему функция называется «рекурсивной»: при обнаружении двух массивов под одним строковым ключом она углубляется в них и повторяет ту же логику слияния для их содержимого.
Примечание: В отличие от array_merge(), которая перезаписывает значения при совпадении строковых ключей и переиндексирует числовые ключи, array_merge_recursive() объединяет совпадающие строковые ключи во вложенные массивы, сохраняя каждое значение.
Вот пример того, как работает array_merge_recursive:
Пример PHP: функция array_merge_recursive
Вывод этого кода будет следующим:
Array
(
[color] => Array
(
[favorite] => Array
(
[0] => red
[1] => green
)
[0] => blue
)
[0] => 5
[1] => 10
)Как видно, функция array_merge_recursive объединила совпадающие ключи входных массивов в подмассивы.
array_merge() vs. array_merge_recursive()
Сравнение двух функций бок о бок наглядно демонстрирует разницу:
<?php
$defaults = ["roles" => ["user"], "name" => "Guest"];
$overrides = ["roles" => ["editor"], "name" => "Ann"];
print_r(array_merge($defaults, $overrides));
print_r(array_merge_recursive($defaults, $overrides));
?>Array // array_merge(): later value wins
(
[roles] => Array
(
[0] => editor
)
[name] => Ann
)
Array // array_merge_recursive(): both values kept
(
[roles] => Array
(
[0] => user
[1] => editor
)
[name] => Array
(
[0] => Guest
[1] => Ann
)
)Обратите внимание: даже name, простая строка, превратилась в массив ["Guest", "Ann"]. Это ключевой подводный камень, описанный ниже: рекурсивное слияние превращает каждый повторяющийся строковый ключ в список, хотите вы того или нет.
Когда использовать array_merge_recursive
Используйте эту функцию, когда цель — собрать значения, а не выбирать одно из них. Распространённый случай — группировка данных, например построение карты категорий и всех относящихся к ним элементов:
<?php
$result = [];
$products = [
["category" => "fruit", "name" => "apple"],
["category" => "fruit", "name" => "pear"],
["category" => "vegetable", "name" => "carrot"],
];
foreach ($products as $product) {
$result = array_merge_recursive(
$result,
[$product["category"] => [$product["name"]]]
);
}
print_r($result);
?>Array
(
[fruit] => Array
(
[0] => apple
[1] => pear
)
[vegetable] => Array
(
[0] => carrot
)
)Подводные камни
- Строковые ключи объединяются, целочисленные — добавляются. Повторяющийся строковый ключ порождает подмассив, даже если оба значения являются скалярными. Если нужно, чтобы более поздние значения перезаписывали более ранние, используйте
array_merge()илиarray_replace_recursive(). - Числовые ключи не сохраняются. Целочисленные ключи всегда перенумеровываются начиная с
0, поэтому нельзя использоватьarray_merge_recursive()для слияния двух массивов по их числовым ключам. Используйте оператор+(объединение), если необходимо сохранить ключи как есть. - Функция спускается только в массивы. Если одна сторона является скаляром, а другая — массивом под тем же ключом, оба просто собираются в список; скаляр не вливается внутрь массива.
Связанные функции
array_merge()— плоское слияние, при котором более поздние строковые ключи перезаписывают более ранние.array_replace_recursive()— рекурсивный обход, как в данной функции, но со заменой значений вместо их накопления.array_combine()— создаёт массив из отдельного массива ключей и массива значений.
Заключение
Функция array_merge_recursive() — правильный выбор, когда нужно объединить значения для общих строковых ключей, а не перезаписывать их: при группировке, агрегации или накоплении данных из нескольких массивов. Помните о двух правилах (строковые ключи объединяются в списки, целочисленные — переиндексируются) и выбирайте array_merge() или array_replace_recursive(), когда нужно поведение «побеждает последнее значение».