Можно ли пропустить параметры со значениями по умолчанию при вызове функции php (5)?

У меня есть это:

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

Возможно ли что-то подобное:

foo('aardvark', <use the default, please>, 'Montague');

Ответов (5)

Решение

Нашел это, что, вероятно, все еще верно:

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

Короткий ответ: нет.

Длинный ответ: да, различными путями, изложенными выше.

Вы в значительной степени нашли ответ, но академический / высокоуровневый подход - это каррирование функций, для которого я, честно говоря, никогда не находил большого применения, но полезно знать, что он существует.

Если это ваша собственная функция, а не одна из ядер PHP, вы можете:

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!']);

Если это ваша функция, вы можете использовать ее null как подстановочный знак и установить значение по умолчанию позже внутри функции:

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";
}

Затем вы можете пропустить их, используя null :

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

Вы можете использовать некоторые причуды, либо передавая все аргументы в виде массива, как предлагает ceejayoz , либо некоторый чрезмерно сложный код, который анализирует func_get_args () и объединяется со списком значений по умолчанию. Чтобы не копировать-вставить, вам придется использовать объекты и черты характера. Наконец, чтобы иметь возможность передавать все виды значений (не исключая null или false, делая их сигналом для подстановки параметров по умолчанию), вам необходимо объявить фиктивный специальный тип DefaultParam. Еще один минус в том, что вам нужно продублировать имена и значения по умолчанию в объявлении функции, если вы хотите получить подсказки по типу или помощь в любой 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');

Примечание: используя preserve_index = true, вы получаете дополнительные аргументы, начиная с их исходного индекса.