Skip to content

Instantly share code, notes, and snippets.

@fjarrett
Last active April 26, 2024 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fjarrett/070182402c85eacf383b64ba5098c3e4 to your computer and use it in GitHub Desktop.
Save fjarrett/070182402c85eacf383b64ba5098c3e4 to your computer and use it in GitHub Desktop.
<?php
/**
* Recursively replaces list arrays and merges associative arrays within a given array.
*
* This function differs from `array_replace_recursive()` by only replacing list arrays
* recursively, while associative arrays are merged. Conversely, it differs from
* `array_merge_recursive()` by merging only associative arrays recursively, while list
* arrays are replaced.
*
* This method ensures list arrays are completely refreshed with the new values,
* and associative arrays are intelligently combined. This preserves structural integrity
* and updates content only where necessary, making it suitable for complex data structures
* where different merge behaviors are needed for lists and associative arrays.
*
* @link https://gist.github.com/fjarrett/070182402c85eacf383b64ba5098c3e4 Example usage
*/
function array_replace_lists_recursive(array $array, array ...$replacements): array
{
foreach ($replacements as $replacement) {
foreach ($replacement as $key => $value) {
if (isset($array[$key]) && is_array($value) && is_array($array[$key])) {
$array[$key] = array_is_list($value) ? $value : array_replace_lists_recursive($array[$key], $value);
} else {
$array[$key] = $value;
}
}
}
return $array;
}
$a = [
'foo' => [
'bar' => 'a',
'baz' => [1, 2, 3],
'qux' => 'c',
'old' => 1,
],
];
$b = [
'foo' => [
'bar' => 'b',
'baz' => [1, 3],
'new' => 'd',
],
];
$c = [
'foo' => [
'qux' => 'updated c',
],
];
echo '<pre>' . var_export(array_replace_lists_recursive($a, $b, $c), true) . '</pre>';
// [
// 'foo' => [
// 'bar' => 'b',
// 'baz' => [1, 3],
// 'qux' => 'updated c',
// 'old' => 0,
// 'new' => 'd',
// ],
// ];
<?php
namespace Tests;
use PHPUnit\Framework\TestCase;
class ArrayReplaceListsRecursiveTests extends TestCase
{
public function test_array_replace_lists_recursive()
{
$array = [
'foo' => [
'bar' => 'a',
'baz' => [1, 2, 3],
'qux' => 'c',
'old' => 1,
],
];
$replacement1 = [
'foo' => [
'bar' => 'b',
'baz' => [4, 5],
'new' => 'd',
],
];
$replacement2 = [
'foo' => [
'qux' => 'updated c',
],
];
$expected = [
'foo' => [
'bar' => 'b',
'baz' => [4, 5],
'qux' => 'updated c',
'old' => 1,
'new' => 'd',
],
];
$actual = array_replace_lists_recursive($array, $replacement1, $replacement2);
$this->assertEquals($expected, $actual);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment