在函数中使用默认参数

问题描述 投票:175回答:12

我对PHP函数的默认值感到困惑。说我有一个这样的功能:

function foo($blah, $x = "some value", $y = "some other value") {
    // code here!
}

如果我想为$ x使用默认参数,并为$ y设置不同的参数怎么办?

我一直在尝试不同的方法,但我变得更加困惑。例如,我尝试了这两个:

foo("blah", null, "test");
foo("blah", "", "test");

但是,这两个都不会为$ x生成正确的默认参数。我也试图通过变量名来设置它。

foo("blah", $x, $y = "test");   

我完全希望这样的事情能奏效。但这根本不符合我的预期。似乎不管我做什么,每次调用该函数时,无论如何我都必须最终键入默认参数。而且我必须缺少明显的东西。

php arguments default
12个回答
162
投票

我建议按如下所示更改函数声明,以便您可以执行所需的操作:

function foo($blah, $x = null, $y = null) {
    if (null === $x) {
        $x = "some value";
    }

    if (null === $y) {
        $y = "some other value";
    }

    code here!

}

通过这种方式,您可以像foo('blah', null, 'non-default y value');那样进行调用,并根据需要运行它,第二个参数$x仍将获得其默认值。

使用此方法,传递空值意味着当您想要覆盖其后的参数的默认值时,需要一个参数的默认值。

如其他答案所述,

默认参数仅用作该函数的最后一个参数。如果要在函数定义中声明默认值,无法忽略一个参数并覆盖其后的一个参数。

如果我有一个可以接受数量不定的参数和类型不同的参数的方法,我通常会声明类似于Ryan P所示答案的函数。

这里是另一个示例(虽然不能回答您的问题,但希望能为您提供有益的参考:

public function __construct($params = null)
{
    if ($params instanceof SOMETHING) {
        // single parameter, of object type SOMETHING
    } else if (is_string($params)) {
        // single argument given as string
    } else if (is_array($params)) {
        // params could be an array of properties like array('x' => 'x1', 'y' => 'y1')
    } else if (func_num_args() == 3) {
        $args = func_get_args();

        // 3 parameters passed
    } else if (func_num_args() == 5) {
        $args = func_get_args();
        // 5 parameters passed
    } else {
        throw new InvalidArgumentException("Could not figure out parameters!");
    }
}

37
投票

可选参数仅在函数调用结束时起作用。如果不指定$ x,则无法在函数中指定$ y的值。某些语言通过命名参数(例如VB / C#)支持此功能,但不支持PHP。

[如果您对参数而不是参数使用关联数组,则可以模拟这一点-即

function foo(array $args = array()) {
    $x = !isset($args['x']) ? 'default x value' : $args['x'];
    $y = !isset($args['y']) ? 'default y value' : $args['y'];

    ...
}

然后按如下所示调用函数:

foo(array('y' => 'my value'));

20
投票

实际上是可能的:

foo( 'blah', (new ReflectionFunction('foo'))->getParameters()[1]->getDefaultValue(), 'test');

您是否愿意这样做是另一个故事:)


更新:

避免此解决方案的原因是:

  • (很丑)
  • 它有明显的开销。
  • 作为其他答案的证明,还有其他选择

但是在以下情况下它实际上可能是有用的:

  • 您不希望/无法更改原始功能。
  • 您可以更改功能,但是:

    • 不使用null(或等效)(请参见DiegoDD的comment
    • 您既不想使用关联,也不想使用func_num_args()
    • 您的生活取决于保存几个LOC

关于性能,very simple test显示使用反射API获取默认参数会使函数调用慢25倍,而仍然需要不到一微秒。您应该知道是否可以忍受。

当然,如果要在循环中使用它,则应事先获取默认值。


10
投票
function image(array $img)
{
    $defaults = array(
        'src'    => 'cow.png',
        'alt'    => 'milk factory',
        'height' => 100,
        'width'  => 50
    );

    $img = array_merge($defaults, $img);
    /* ... */
}

4
投票

我知道的唯一方法是忽略参数。忽略参数的唯一方法是重新排列参数列表,以便要忽略的参数位于HAVE要设置的参数之后。例如:

function foo($blah, $y = "some other value", $x = "some value")

然后您可以像这样调用foo:

foo("blah", "test");

这将导致:

$blah = "blah";
$y = "test";
$x = "some value";

3
投票

我最近遇到了这个问题,并找到了这个问题和答案。尽管上述问题起作用了,但问题在于它们没有向支持它的IDE显示默认值(如PHPStorm)。

enter image description here

如果使用null,则将其保留为空白将不知道该值是什么。

我更喜欢的解决方案是将默认值也放入函数定义中:

protected function baseItemQuery(BoolQuery $boolQuery, $limit=1000, $sort = [], $offset = 0, $remove_dead=true)
{
    if ($limit===null) $limit =1000;
    if ($sort===null) $sort = [];
    if ($offset===null) $offset = 0;
    ...

唯一的区别是,我需要确保它们相同-但我认为要付出额外的清晰度是不小的代价。


2
投票

您不能直接执行此操作,但是只需进行一点点代码摆弄就可以进行仿真。

function foo($blah, $x = false, $y = false) {
  if (!$x) $x = "some value";
  if (!$y) $y = "some other value";

  // code
}

1
投票
<?php
function info($name="George",$age=18) {
echo "$name is $age years old.<br>";
}
info();     // prints default values(number of values = 2)
info("Nick");   // changes first default argument from George to Nick
info("Mark",17);    // changes both default arguments' values

?>

0
投票

是这种情况,当对象更好时-因为您可以将对象设置为容纳x和y,设置默认值等。

具有数组的方法接近于创建对象(实际上,对象是一堆参数和函数,它们将对对象起作用,而采用数组的函数将对一些一堆ov参数起作用)

当然,您总是可以做一些技巧来将null或类似的内容设置为默认值


0
投票

您还可以检查是否有空字符串作为参数,因此可以像这样调用:

foo('blah', "", 'non-default y value', null);

功能下方:

function foo($blah, $x = null, $y = null, $z = null) {
    if (null === $x || "" === $x) {
        $x = "some value";
    }

    if (null === $y || "" === $y) {
        $y = "some other value";
    }

    if (null === $z || "" === $z) {
        $z = "some other value";
    }

    code here!

}

填写null""都没关系,您仍然会得到相同的结果。


0
投票

将数组而不是单个参数传递给函数,并使用空合并运算符(PHP 7 +)。

[下面,我传递一个包含2个项目的数组。在该函数内部,我正在检查是否设置了item1的值(如果未分配默认文件库)。

$args = ['item2' => 'item2',
        'item3' => 'value3'];

    function function_name ($args) {
        isset($args['item1']) ? $args['item1'] : 'default value';
    }

0
投票

我用空合并运算符]支付的2美分??(自PHP 7起)

function foo($blah, $x = null, $y = null) {
    $varX = $x ?? 'Default value X';
    $varY = $y ?? 'Default value Y';
    // ...
}

您可以在repl.it上查看更多示例

© www.soinside.com 2019 - 2024. All rights reserved.