在函数调用中,是否可以跳过具有默认值的参数?

8

我有这个:

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

类似这样的东西是否可行:
foo('aardvark', <use the default, please>, 'Montague');

1
有一个提案计划在php5.5中实现此功能[https://wiki.php.net/rfc/skipparams]。 - Shahid
Syntactic 是什么情况?https://github.com/topclaudy/php-syntactic - cjdaniel
6个回答

12

如果这是您自己的函数,您可以使用 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"

5
如果这是你自己的函数而不是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!']);

4

我找到了这个链接,它可能仍然正确:

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

简短的回答是:不行。

长的回答是:可以通过各种拙劣的方式实现,这些方式在上面的链接中有详细介绍。


0

你可以使用一些技巧,比如像ceejayoz建议的那样将所有参数作为数组传递,或者使用一些过于复杂的代码来解析func_get_args()并与默认列表合并。为了避免复制粘贴,你需要使用对象和traits。最后,为了能够传递各种值(包括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 时,您可以获得额外的参数,以便从它们的原始索引开始。

0

从 PHP 8 开始,使用命名参数

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

这样可以让你绕过任意数量的参数,使它们采用默认值。这在冗长的函数中非常有帮助,比如setcookie

setcookie('macadamia', httponly:true); // skips over 5 parameters

请注意,命名参数要求所有非可选参数都必须被传递。这些参数可以按位置传递(就像我在这里做的那样,没有名称),也可以按任何顺序使用名称传递。

0

你差不多找到答案了,但学术/高级的方法是函数柯里化,我老实说从来没觉得有太大用处,但知道它存在还是很有用的。


我认为柯里化对于默认参数值无能为力-它们基本上是互相排斥的概念。 - jpalecek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接