Should my PHP functions accept an array of arguments or should I explicitly request arguments?

In a PHP web application I'm working on, I see functions defined in two possible ways.

Approach 1:

function myfunc($arg1, $arg2, $arg3)

Approach 2:

// where $array_params has the structure array('arg1'=>$val1, 'arg2'=>$val2, 'arg3'=>$val3)
function myfunc($array_params)

When should I use one approach over another? It seems that if system requirements keep changing, and therefore the number of arguments for myfunc keep changing, approach 1 may require a lot of maintenance.


If the system is changing so often that using an indexed array is the best solution, I'd say this is the least of your worries. :-)

In general functions/methods shouldn't take too many arguments (5 plus or minus 2 being the maximum) and I'd say that you should stick to using named (and ideally type hinted) arguments. (An indexed array of arguments only really makes sense if there's a large quantity of optional data - a good example being configuration information.)

As @Pekka says, passing an array of arguments is also liable to be a pain to document and therefore for other people/yourself in 'n' months to maintain.

Update-ette...

Incidentally, the oft mentioned book Code Complete examines such issues in quite a bit of detail - it's a great tome which I'd highly recommend.


Using a params array (a surrogate for what is called "named arguments" in other languages") is great - I like to use it myself - but it has a pretty big downside: Arguments are not documentable using standard phpDoc notation that way, and consequently, your IDE won't be able to give you hints when you type in the name of a function or method.


I find using an optional array of arguments to be useful when I want to override a set of defaults in the function. It might be useful when constructing an object that has a lot of different configuration options or is just a dumb container for information. This is something I picked up mostly from the Ruby world.

An example might be if I want to configure a container for a video in my web page:

function buildVideoPlayer($file, $options = array())
{
  $defaults = array(
    'showAds' => true,
    'allowFullScreen' = true,
    'showPlaybar' = true
  );

 $config = array_merge($defaults, $options);

 if ($config['showAds']) { .. }
}

$this->buildVideoPlayer($url, array('showAds' => false));

Notice that the initial value of $options is an empty array, so providing it at all is optional.

Also, with this method we know that $options will always be an array, and we know those keys have defaults so we don't constantly need to check is_array() or isset() when referencing the argument.