I have two arrays:
The original:
array(2) {
'app_name' =>
string(15) "dropcat-default"
'site' =>
array(1) {
'environment' =>
array(7) {
'drush_alias' =>
NULL
'backup_path' =>
string(6) "backup"
'config_name' =>
NULL
'original_path' =>
string(33) "/var/www/webroot/shared/some_path"
'symlink' =>
string(43) "/var/www/webroot/mysite_latest/symlink_path"
'url' =>
string(17) "http://localhost"
'name' =>
string(11) "mystagesite"
}
}
}
And the one with overrides:
array(2) {
'app_name' =>
string(17) "dropcat-overrides"
'site' =>
array(1) {
'environment' =>
array(1) {
'drush_alias' =>
string(6) "foobar"
}
}
}
I want to replace the overrides in the original array, but keep the keys that are not present in the override - using array_replace
just writes over the existing ones, because I have arrays in arrays. Is there a simple way to solve this?
function _merge_array_rec($arr, $arr2, $i = 0)
{
foreach ($arr2 as $key => $value)
{
if (!isset($arr[$key]))
{
$arr[$key] = $value;
}
else
{
if (is_array($value))
{
$arr[$key] = _merge_array_rec($arr[$key], $arr2[$key], $i + 1);
}
else
{
$arr[$key] = $value;
}
}
}
return $arr;
}
$merge_array = _merge_array_rec($array1, $array2);
array_replace_recursive gets it done for multi dimensional arrays.
As for single dimension arrays, looping through the original array then checking if the overriding array has this value is fun enough.
Something similar to this :
$original=array();
$overriding=array();
foreach($original as $key => $value){
if(isset($overriding[$key]) && !empty($overriding[$key])){
$original[$key]=$overriding[$key];
}
}
Hope this helps
array_key_exists
should be used instead of isset
, because isset
ignores NULL
.$overrides
should be validated, shouldn't it?Try it out.
<?php
function array_replace_recursive_if_valid(array $defaults, array $overrides) {
foreach ($overrides as $key => $value) {
if (!array_key_exists($key, $defaults)) {
continue;
}
if (is_array($defaults[$key]) && is_array($value)) {
$defaults[$key] = array_replace_recursive_if_valid($defaults[$key], $value);
continue;
}
if (!is_array($defaults[$key]) && !is_array($value)) {
$defaults[$key] = $value;
continue;
}
}
return $defaults;
}
$defaults = [
'app_name' => 'dropcat-default',
'site' => [
'environment' => [
'drush_alias' => null,
'back_path' => 'packup',
'config_name' => null,
'original_path' => '/var/www/webroot/shared/some_path',
'symlink' => '/var/www/webroot/mysite_latest/symlink_path',
'url' => 'http://localhost',
'name' => 'mystagesite',
],
],
];
$overrides = [
'app_name' => 'dropcat-overrides',
'this is invalid' => 'foo',
'site' => [
'environment' => [
'drush_alias' => 'foobar',
'url' => ['this is invalid'],
],
],
];
var_export(array_replace_recursive_if_valid($defaults, $overrides));
In the end, I ended up doing it like this:
$configs = array_replace_recursive($default_config, $env_config);
It covered my use case.