array_merge_recursive

Description

array_merge_recursive() merges the elements of
one or more arrays together so that the values of one are appended
to the end of the previous one. It returns the resulting array.

If the input arrays have the same string keys, then the values for
these keys are merged together into an array, and this is done
recursively, so that if one of the values is an array itself, the
function will merge it with a corresponding entry in another array
too. If, however, the arrays have the same numeric key, the later
value will not overwrite the original value, but will be appended.

There are a lot of examples here for recursion that are meant to behave more like array_merge() but they don't get it quite right or are fairly customised. I think this version is most similar, takes more than 2 arguments and can be renamed in one place:

I little bit improved daniel's and gabriel's contribution to behave more like original array_merge function to append numeric keys instead of overwriting them and added usefull option of specifying which elements to merge as you more often than not need to merge only specific part of array tree, and some parts of array just need to let overwrite previous. By specifying helper element mergeWithParent=true, that section of array will be merged, otherwise latter array part will override former. First level of array behave as classic array_merge.

The presence of NULLs; here is an example of the issue and a fix. Although it may not be apparent, if using array_merge_recursive in a loop to combine results from a database query or some other function, you can corrupt your result when NULLs are present in the data. I discovered this when migrating from an Oracle DB to a MySQL DB. I had to match the array structure returned from the PHP function calling the DB and got bit. The array_walk call fixed this for me.
This is a simple example that lacks any DB calls and looping. Assume your array had the DB column names (first, last, and age) and you needed to combine the data in a multi-dimensional array in which the column name is an array key with all rows beneath it. The corruption occurs in $a3. If using element position 2, one could create the fictitious 'pete johnson' because of the collapsing of elements.

Short description: If one of the Arguments isn't an Array, first Argument is returned. If an Element is an Array in both Arrays, Arrays are merged recursively, otherwise the element in $ins will overwrite the element in $arr (regardless if key is numeric or not). This also applys to Arrays in $arr, if the Element is scalar in $ins (in difference to the previous approach).

In Addition to felix dot ospald at gmx dot de in my opinion there is no need to compare keys with type-casting, as a key always is changed into an integer if it could be an integer. Just try

$a = array('1'=>'1');echo gettype(key($a));

It will echo 'integer'. So for having Integer-Keys simply appended instead of replaced, add the Line:

elseif (is_int($k)) $arr[] = $v;

A Condition I used is:

elseif (is_null($v)) unset($arr[$k]);

So a NULL-Value in $ins will unset the correspondig Element in $arr (which is different to setting it to NULL!). This may be another Addition to felix dot ospald at gmx dot de: The absolute correct way to check for a Key existing in an Array is using array_key_exists() (not needed in the current context, as isset() is combined with is_array()). array_key_exists() will return TRUE even if the Value of the Element is NULL.

And the last one: If you want to use this approach for more than 2 Arrays, simply use this:

<?php/** * Merges any number of arrays / parameters recursively, replacing * entries with string keys with values from latter arrays. * If the entry or the next value to be assigned is an array, then it * automagically treats both arguments as an array. * Numeric entries are appended, not replaced, but only if they are * unique * * calling: result = array_merge_recursive_distinct(a1, a2, ... aN)**/

Merging arrays recursively some problem about existing keys, so that i wrote the function above like this:

function merge($array0, $array1) { // Result $merged = array();

foreach (func_get_args() as $array) { // Check incoming argument is array if (is_array($array)) { foreach ($array as $key => $value) { // Check there is an array with the key: $key if (isset($merged[$key])) { // Check the value is array if (is_array($value)) { // So we must merge current value with the existing array $merged[$key] = call_user_func_array(__FUNCTION__, $merged[$key], $value); } else { if (!is_array($merged[$key])) { // If the existing array with the key: $key not an array // We make it an array $merged[$key] = array($merged[$key]); }

Values with numeric keys are always appended. The index of the merge array is determined by the startindex of the first array. Value4s with numeric keys seems always appended.If a key looks like an integer, array_merge_recursive will interpret the string as an number.

In the example $arr['farbe']['22'] = 'grün' wil be found after array_merge_recursive in $res['farbe'][33]

I ran into a fairly unique situation where array_merge_recursive ALMOST did what I wanted, but NOT QUITE. I read through all of the comments, and I didn't find anything that really helped me. I saw a lot of functions submitted that were just trying to recreate array_replace_recursive. This is not that.

Take a look at the code and try it out. Hopefully it helps someone in need!

class Arr{ /** * Merge multiple arrays. * * This is similar to, but slightly different than array_merge_recursive. * The main difference is that it will merge like keys in subarrays, * instead of simply pushing them into the output array. * * @param array ...$array * * @return array */ public static function merge() { /** Initialize the output array */ $merged = [];

/** Go through each argument */ foreach (func_get_args() as $array) { /** Go through each key/value of this array */ foreach ($array as $key => $value) { /** * If this key isn't set on merged, * then it needs to be set for the first time */ if (! isset($merged[$key])) { /** * Before we can set it, we must make sure * to dive into this value if it is an array, * so that all of its children will be processed. */ if (is_array($value)) { $value = static::merge($value); }

/** * Now that we're happy with this value, * and we're sure that, if it is an array, * all of its children have been processed, * let's go ahead and set it. */ $merged[$key] = $value;

/** We can skip the rest of the loop */ continue; }

/** * We're here because we want to set a key * that is already set on merged. We don't want * to overwrite anything - we want to add to it. * So, we need to make sure that we're working with an array. */ if (! is_array($merged[$key])) { $merged[$key] = [$merged[$key]]; }

/** * Before we push the value onto the array, * we need to check to see if it is an array itself. * If it is, then we need to make sure all of its children * are processed. We do this by merging all of the children * together. This is where it differs from array_merge_recursive, * which would simply push the children onto the end of the array. */ if (is_array($value)) { $value = forward_static_call_array([Arr::class, 'merge'], $value); }

This function didn't work for me - or it didn't do what I thought it would. So I wrote the below function, which merges two arrays, and returns the resulting array. The base array is the left one ($a1), and if a key is set in both arrays, the right value has precedence. If a value in the left one is an array and also an array in the right one, the function calls itself (recursion). If the left one is an array and the right one exists but is not an array, then the right non-array-value will be used.

*Any key only appearing in the right one will be ignored* - as I didn't need values appearing only in the right in my implementation, but if you want that you could make some fast fix.

session_start();$x = array(k1=>12, k2=>array(kxx=>'forget me', kyy=>'I was allways here')); // do you have any of this on $_SESSION$rpl = array(k2=>array(kxx=>'I am a replaced value',kzz=>'I am a new value'));arr2sess($x, array('deep','deep','in_session')); // you can use this way arr2sess($x); // or thisarr2sess($rpl); // to merge parts with the $_SESSION

$w = array(120, q=>array(199,100)); // works the same way on numeric keysarr2sess($w, array('one','two'));arr2sess($w);

I've tried these array_merge_recursive functions without much success. Maybe it's just me but they don't seem to actually go more than one level deep? As with all things, its usually easier to write your own, which I did and it seems to work just the way I wanted. Anyways, my function hasn't been tested extensively, but it's a simple function, so in hopes that this might be useful to someone else I'm sharing.

Also, the PHP function array_merge_recursive() didn't work for my purposes because it didn't overwrite the values like I needed it to. You know how it works, it just turns it into an array with multiple values... not helpful if your code is expecting one string.

function array_merge_recursive_unique($array1, $array2) {

// STRATEGY /* Merge array1 and array2, overwriting 1st array values with 2nd array values where they overlap. Use array1 as the base array and then add in values from array2 as they exist.

Walk through each value in array2 and see if a value corresponds in array1. If it does, overwrite with second array value. If it's an array, recursively execute this function and return the value. If it's a string, overwrite the value from array1 with the value from array2.

If a value exists in array2 that is not found in array1, add it to array1. */

<?php/** * Merges any number of arrays of any dimensions, the later overwriting * previous keys, unless the key is numeric, in whitch case, duplicated * values will not be added. * * The arrays to be merged are passed as arguments to the function. * * @access public * @return array Resulting array, once all have been merged */function array_merge_replace_recursive() {// Holds all the arrays passed$params = & func_get_args ();

// First array is used as the base, everything else overwrites on it$return = array_shift ( $params );

A small improvement upon the previously posted array_merge_recursive_distinct functions (based on daniel's version). This implementation preserves the parameter input from the original, you can pass an infinite amount of array's to merge.

If you desire correct and performant behaviour (in contrast to the other postings) use this code. It works as documented above.If you want that keys are always perserved and not appended or renumbered if they are numeric comment out the "if (((string) $key) === ((string) intval($key)))" case.@spambegone at cratemedia dot com: using empty is not right way to check if an item is in the array use isset!

This function tends to reindex arrays, which is not mentioned in the function description.

I just tried to run that function on a three dimensional array, containing errormessages.The first dim. contains the severity of the error ('warn', 'crit') the second dim the linenumber (numerical) and the third one consists of errormessages

Please be aware that under circumstances where you have both the key and value common between the two arrays at a given node,array_merge_recursive() will behave differently if that value is NULL,as opposed to a non-null value.

i.e., I expected the results of the first two sections below to have the same structure, but they don't. If this might apply to you, please see for yourself.