tags:

views:

118

answers:

4

I have an array with default settings, and one array with user-specified settings. I want to merge these two arrays so that the default settings gets overwritten with the user-specified ones.

I have tried to use array_merge, which does the overwriting like I want, but it also adds new settings if the user has specified settings that doesn't exist in the default ones. Is there a better function I can use for this than array_merge? Or is there a function I can use to filter the user-specified array so that it only contains keys that also exist in the default settings array?

Example of what I want

$default = array('a' => 1, 'b' => 2);
$user = array('b' => 3, 'c' => 4);

// Somehow merge $user into $default so we end up with this:
Array
(
    [a] => 1
    [b] => 3
)
A: 
foreach($user_settings as $key=>$val){   
    $global_settings[$key] = $val; 
}

?

Robus
That does exactly what he said he didn't want it to do.
Chad Birch
Yup, hehe. I don't want anything that doesn't exist in the default array to be added.
Svish
I suppose that could work if I add an `if(isset)`, but I was curious to see if there are any php function that can do it out of the box for me. Especially since there are quite a bit of array related functions that I don't quite understand...
Svish
Uhh, I fail at reading as it seems
Robus
+1  A: 

You can actually just add two arrays together ($user+$default) instead of using array_merge.

If you want to stop any user settings that don't exist in the defaults you can use array_intersect_key:

Returns an associative array containing all the entries of array1 which have keys that are present in all arguments

Example:

$default = array('a' => 1, 'b' => 2);
$user = array('b' => 3, 'c' => 4);

// add any settings from $default to $user, then select only the keys in both arrays
$settings = array_intersect_key($user + $default, $default);

print_r($settings);

Results:

Array
(
    [b] => 3
    [a] => 1
)

The keys/values (and order) are selected first from $user in the addition, which is why b comes before a in the array, there is no a in $user. Any keys not defined in $user that are defined in $default will then be added to the end of $user. Then you remove any keys in $user + $default that aren't defined in $default.

gnarf
If a key exists in the `$userSettings` but not in `$defaultSettings`, you would copy it over to `$settings`. He doesn't want that to happen.
Chad Birch
This has the same problem as far as I can see from my tests. If there are any settings in `$userSettings` that are not defined in `$defaultSettings`, then they will be taken also. I want all keys not defined in `$defaultSettings` to be ignored and not present in my final `$settings` array.
Svish
@chad ) )
gnarf
Hm... missed the `+ $defaultSettings` at first, but when I added that this totally works :) Awesome!
Svish
A: 

It's probably simplest to just loop over the keys in the default-settings array, if you only want to consider those. So you can do something like this:

foreach ($default_settings AS $key => $default_value)
{
    if (array_key_exists($key, $user_settings))
    {
        $combined_settings[$key] = $user_settings[$key];
    }
    else
    {
        $combined_settings[$key] = $default_value;
    }
}
Chad Birch
Yeah, seems like something along these lines will be the way to go. Was just hoping PHP had something more clever up it's sleeve and that I could get to know a new and interesting php function, hehe.
Svish
Well, if you want "clever" I'd go with gnarf's answer. But honestly, if I came across that line of code somewhere, I'd have no clue at all what it was doing. So please add an explanation in a comment if you do use that, for the sanity of future maintainers (including yourself).
Chad Birch
I've seen the pattern I used in Zend Framework stuff, and the first time I said "wtf is this doing", but luckily with PHP is easy enough to go to http://php.net/array_intersect_key and figure it out.
gnarf
+1  A: 
foreach($default as $key=>$val){   
  if (isset($user[$key]))
  {
    $settings[$key] = $user[$key];
  } else {
    $settings[$key] = $default[$key];
  } 
}

I think this is what you want.

Wouldn't this fail if a key was not set in the $user_settings array?
Svish
You are right, we also need an isset().