0

Named parameters are great for a long list of options in a PHP user defined function or class. But what about nested options?

Eg:

function foobar($foo,$bar,$options=array()) {

    $default_options = array('option1'=>'','option2'=>'hello','option3'=>array('option1'=>true,'option2'=>''));

    $options = array_merge($default_options,(array)$options);
}

So option 3 is another array with suboptions. Would we need to put them in a for loop to merge the suboptions too? What would you guys do in this case?

EDIT:

This is the function call:

foobar('foo','bar',array('option1'=>'foo','option3'=>array('option1'=>false)));

Ending structure for $options:

array(
'option1'=>'foo',
'option2'=>'hello',
'option3'=>array(
    'option1'=>false,
    'option2'=>''
);
DADU
  • 6,482
  • 7
  • 42
  • 64
  • Check array_merge(array1, array2); – powtac Jan 28 '11 at 15:49
  • Yes, but I'm doing that already: $options = array_merge($default_options,(array)$options); – DADU Jan 28 '11 at 15:53
  • One other option would be to add every nested options array as an extra parameter. Hard to choose between nested array or one extra parameter which makes it a positional parameter. – DADU Jan 28 '11 at 16:22

4 Answers4

2

There is array_merge_recursive(), but it may not do what you actually expect.

Here is a recursive version or array_merge() which actually behaves like array_merge():

function array_merge_recursive_2($a, $b) {
        foreach($b as $key => $value) {
                if (isset($a[$key]) && is_array($a[$key]) && is_array($value)) {
                        $a[$key] = array_merge_recursive_2($a[$key], $value);
                } else {
                        $a[$key] = $value;
                }
        }
        return $a;
}
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
1

Use array_merge_recursive(). This will merge subarrays as well.

goto-bus-stop
  • 11,655
  • 2
  • 24
  • 31
  • 1
    This function does not do what one could expect at first. When a key exists in both array, this function will just return an array with both values in it. (Does not behave really like [`array_merge`](http://php.net/array_merge).) – Arnaud Le Blanc Jan 28 '11 at 16:01
  • I wasn't aware of that, I never used the function before, just guessed there would be one as PHP has billions of functions that aren't really needed. Anyway, good to know xD. – goto-bus-stop Jan 28 '11 at 16:04
1

Why not just use the func_get_args function?

function yourFunction($keys) {
    $default_options = array('test', array('test1' => array('test2')), 'test3');
    $options = func_get_args();
    array_shift($options);

    $options = array_combine($keys, $options); 
    $options = array_merge($default_options, $options);

    print_r($options);
}

// Usage
yourFunction(array('option1', 'option2', 'option3', 'option4'), 'optionval1', array('optionval2-1', 'optionval2-2'), 'optionval3', 4);

This way you have an array to start with and do not need to worry about anything else, and it can accept any number of parameters / arguments!

EDIT:

(Second edit, added the $keys as the first param) Modified the function above, here is the output. Not sure exactly what format of output you are looking for. So you may need to post the ending array structure you are after for your initial data given.

Array
(
    [0] => test
    [1] => Array
        (
            [test1] => Array
                (
                    [0] => test2
                )

        )

    [2] => test3
    [option1] => optionval1
    [option2] => Array
        (
            [0] => optionval2-1
            [1] => optionval2-2
        )

    [option3] => optionval3
    [option4] => 4
)
Jim
  • 18,673
  • 5
  • 49
  • 65
  • That's good for the first step, but what about merging it with the defaults then? – DADU Jan 28 '11 at 16:14
  • Great you added the output. But it doesn't really make sense to have numbered keys because named parameters should have named keys. – DADU Jan 28 '11 at 16:25
  • ...where are the parameters named at? The "option1" etc was meant to be the value, not necessarily the name. You could pass in a "keys" array as the first parameter always, then shift it off and use `array_combine` if you want. Updating with that scenario. – Jim Jan 28 '11 at 16:40
0

Look what I've found in the CakePHP framework:

function merge($arr1, $arr2 = null) {

    $args = func_get_args();

    $r = (array)current($args);

    while (($arg = next($args)) !== false) {
        foreach ((array)$arg as $key => $val)    {
            if (is_array($val) && isset($r[$key]) && is_array($r[$key])) {
                $r[$key] = merge($r[$key], $val);
            } elseif (is_int($key)) {
                $r[] = $val;
            } else {
                $r[$key] = $val;
            }
        }
    }


    return $r;
}

It's a shame that the built in PHP merge function can't do this for us but this is a great alternative.

DADU
  • 6,482
  • 7
  • 42
  • 64