在函数中使用默认参数

时间:2012-02-06 20:36:37

标签: php arguments default

我对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");   

我完全期待这样的事情发挥作用。但它根本无法实现。似乎无论我做什么,每次调用函数时,我都必须最终输入默认参数。而且我必须遗漏一些明显的东西。

14 个答案:

答案 0 :(得分:146)

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

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

答案 1 :(得分:35)

可选参数仅在函数调用结束时起作用。如果没有指定$ 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'));

答案 2 :(得分:19)

实际上可能是:

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

你是否愿意这样做是另一回事:)

更新

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

  • (可以说)丑陋
  • 它有明显的开销。
  • 正如另一个回答证明,有其他选择

但在以下情况下它实际上很有用:

  • 你不想/不能改变原来的功能。
  • 您可以更改功能,但是:

    • 使用null(或等效物品)不是一种选择(参见DiegoDD的comment
    • 您不想使用关联或使用func_num_args()
    • 你的生活取决于拯救几个LOC

关于性能,very simple test表明使用Reflection API获取默认参数会使函数调用慢25倍,而它仍然需要小于1微秒。你应该知道你是否可以忍受。

当然,如果你想在循环中使用它,你应该事先得到默认值。

答案 3 :(得分:10)

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

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

答案 4 :(得分:3)

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

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

然后你可以调用foo:

foo("blah", "test");

这将导致:

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

答案 5 :(得分:3)

在 PHP 8 中,我们可以使用命名参数来解决这个问题。

所以我们可以解决这个问题的原始发布者描述的问题:

<块引用>

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

与:

foo(blah: "blah", y: "test");

参考:https://wiki.php.net/rfc/named_params(特别是“跳过默认值”部分)

答案 6 :(得分:2)

你不能直接这样做,但是一点点代码就可以模仿。

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

  // code
}

答案 7 :(得分:2)

我最近遇到了这个问题并找到了这个问题和答案。虽然上述问题有效,但问题是他们没有向支持它的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;
    ...

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

答案 8 :(得分: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

?>

答案 9 :(得分:1)

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

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

您可以在我的repl.it

上查看更多示例

答案 10 :(得分:0)

这种情况,当对象更好时 - 因为你可以设置你的对象来保持x和y,设置默认值等。

使用数组的方法接近创建对象(事实上,对象是一堆参数和函数,它们将在对象上工作,而函数获取数组将工作在一些ov参数上)

你总是可以做一些技巧来设置null或类似的东西作为默认

答案 11 :(得分: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""并不重要,您仍会得到相同的结果。

答案 12 :(得分:0)

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

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

<xs:simpleType name="TFIndicator">
    <xs:annotation>
        <xs:documentation source="Name" xml:lang="EN">
            TFIndicator
        </xs:documentation>
        <xs:documentation source="Definition" xml:lang="EN">
            A flag indicating a True or False value.
        </xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:boolean"/>
</xs:simpleType>

答案 13 :(得分:0)

PHP 8 的做法:

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