Home » Php » Is it possible to skip parameters that have default values in a php(5) function call?

Is it possible to skip parameters that have default values in a php(5) function call?

Posted by: admin July 12, 2020 Leave a comment

Questions:

I have this:

function foo($a='apple', $b='brown', $c='Capulet') {
    // do something
}

Is something like this possible:

foo('aardvark', <use the default, please>, 'Montague');
How to&Answers:

If it’s your function, you could use null as wildcard and set the default value later inside the function:

function foo($a=null, $b=null, $c=null) {
    if (is_null($a)) {
        $a = 'apple';
    }
    if (is_null($b)) {
        $b = 'brown';
    }
    if (is_null($c)) {
        $c = 'Capulet';
    }
    echo "$a, $b, $c";
}

Then you can skip them by using null:

foo('aardvark', null, 'Montague');
// output: "aarkvark, brown, Montague"

Answer:

If it’s your own function instead of one of PHP’s core, you could do:

function foo($arguments = []) {
  $defaults = [
    'an_argument' => 'a value',
    'another_argument' => 'another value',
    'third_argument' => 'yet another value!',
  ];

  $arguments = array_merge($defaults, $arguments);

  // now, do stuff!
}

foo(['another_argument' => 'not the default value!']);

Answer:

Found this, which is probably still correct:

http://www.webmasterworld.com/php/3758313.htm

Short answer: no.

Long answer: yes, in various kludgey ways that are outlined in the above.

Answer:

You pretty much found the answer, but the academic/high-level approach is function currying which I honestly never found much of a use for, but is useful to know exists.

Answer:

You can use some quirks, either passing all arguments as an array like ceejayoz suggests, or some overcomplicated code that parses func_get_args() and merges with a list of defaults. Not to copy-paste it, you’ll have to use objects and traits. Finally, to be able to pass all kinds of values (not excluding null or false by making them a signal for default param substitution), you’ll have to declare a dummy special type DefaultParam.
Another minus is that you have to duplicate the names and default values in the function declaration, if you want to get type hints or help in any IDE.

class DefaultParam {}

trait multi_arg_functions
{
  private static function multi_arg($defaults, $list, $preserve_index = false)
  {
    $arg_keys = array_slice(array_keys($defaults), 0, count($list));

    if ($preserve_index) {
      $listed_arguments = array_slice($list, 0, count($arg_keys));
      $extras = array_slice($list, count($arg_keys), null, true);
    } else {
      $listed_arguments = array_splice($list, 0, count($arg_keys));
      $extras = &$list;
    }
    unset($list);

    $arguments = array_combine($arg_keys, $listed_arguments);
    $arguments = array_filter($arguments, function ($entry) {
      return !($entry instanceof DefaultParam); //remove entries that mean default, a special class in this case
    });
    $arguments = array_merge($defaults, $arguments);

    return [$arguments, $extras];
  }
}

class b {
  use multi_arg_functions;

  static function func1($an_argument = 'a value', $another_argument = 'another value', $third_argument = 'yet another value') { //give defaults here to get hints in an IDE
      list($args, $extras) = self::multi_arg( //note: duplicate names and defaults
          [
          'an_argument' => 'a value',
          'another_argument' => 'another value',
          'third_argument' => 'yet another value!',
          ], func_get_args());

      echo json_encode(['args' => $args, 'extras' => $extras])."\n";
  }
}

$default_param = new DefaultParam();

b::func1('value 1');
b::func1('value 2', $default_param, 'third argument');
b::func1('value 3', $default_param, 'third argument', 'fourth argument');

Note: by using preserve_index = true you get the extra arguments to start from their original index.