Skip to content

Instantly share code, notes, and snippets.

@josephj
Last active September 10, 2023 07:52
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save josephj/5028375 to your computer and use it in GitHub Desktop.
Save josephj/5028375 to your computer and use it in GitHub Desktop.
Useful PHP script when you want to merge multiple arrays like Y.merge().
<?php
/**
* Copy from http://www.php.net/manual/en/function.array-merge-recursive.php#92195
*
* array_merge_recursive does indeed merge arrays, but it converts values with duplicate
* keys to arrays rather than overwriting the value in the first array with the duplicate
* value in the second array, as array_merge does. I.e., with array_merge_recursive,
* this happens (documented behavior):
*
* array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('org value', 'new value'));
*
* array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
* Matching keys' values in the second array overwrite those in the first array, as is the
* case with array_merge, i.e.:
*
* array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('new value'));
*
* Parameters are passed by reference, though only for performance reasons. They're not
* altered by this function.
*
* @param array $array1
* @param array $array2
* @return array
* @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
* @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
*/
function array_merge_recursive_distinct(array &$array1, array &$array2)
{
$merged = $array1;
foreach ($array2 as $key => &$value)
{
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key]))
{
$merged[$key] = array_merge_recursive_distinct($merged[$key], $value);
}
else
{
$merged[$key] = $value;
}
}
return $merged;
}
?>
<?php
function array_merge_recursive_distinct(array &$array1, array &$array2)
{
$merged = $array1;
foreach ($array2 as $key => &$value)
{
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key]))
{
$merged[$key] = array_merge_recursive_distinct($merged[$key], $value);
}
else
{
$merged[$key] = $value;
}
}
return $merged;
}
$config = array(
/**
* CSS/JS seed URLs.
*/
"seed" => array(
"css" => "combo/?g=css",
"js" => "combo/?g=js",
),
/**
* Combo base URL.
*/
"base" => "combo/?f=",
/**
* Combo separator.
*/
"separator" => ",",
/**
* YUI default configuration.
*/
"yui" => array(
"config" => array(
"lang" => "en-US",
),
"callback" => "(new Y.ModuleManager()).startAll();",
),
);
$options = array(
"yui" => array(
"config" => array(
"lang" => "zh-TW",
),
),
);
print_r(array_merge_recursive_distinct($config, $options));
?>
@reindert-vetter
Copy link

Thanks. You can replace function array_merge_recursive_distinct(array &$array1, array &$array2) with function array_merge_recursive_distinct(array $array1, array $array2)

@jonathan-connecteam
Copy link

Thanks a lot!
I added an option to only replace truthy values (useful when you don't want empty strings to overwrite existing strings):

function array_merge_recursive_distinct ($array1, $array2, $only_reaplce_truthy_values = false) {
  $merged = $array1;
  foreach ($array2 as $key => $value) {
    if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
      $merged[$key] = array_merge_recursive_distinct($merged[$key], $value, $only_reaplce_truthy_values);
    } else {
      if ($only_reaplce_truthy_values) {
        $merged[$key] = $value ?: $array1[$key];
      } else {
        $merged[$key] = $value;
      }
    }
  }
  return $merged;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment