在函数中使用默认参数

我对PHP函数的默认值感到困惑。 说我有这样的function:

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

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

我一直在尝试不同的方式,而我越来越困惑。 例如,我试了这两个:

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

但是这两者都不会导致$ x的默认参数。 我也试图通过variables名来设置它。

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

我完全期待这样的工作。 但是,它并不像我所期望的那样工作。 似乎不pipe我做什么,我将不得不最终input默认参数,每次我调用该函数。 我一定会错过一些明显的东西。

我build议改变函数声明如下,所以你可以做你想做的事情:

 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仍然得到它的默认值。

使用这个方法,传递一个空值意味着当你想覆盖一个参数的默认值时,你想要一个参数的默认值。

正如其他答案所述,

默认参数只作为函数的最后一个参数。 如果要在函数定义中声明默认值,则无法省略一个参数并覆盖其后的参数。

如果我有一个方法可以接受不同数量的参数和不同types的参数,我经常会声明与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!"); } } 

可选参数仅在函数调用结束时起作用。 在没有指定$ 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')); 
 function image(array $img) { $defaults = array( 'src' => 'cow.png', 'alt' => 'milk factory', 'height' => 100, 'width' => 50 ); $img = array_merge($defaults, $img); /* ... */ } 

这实际上是可能的:

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

你是否想要这样做是另一回事:)


更新:

避免这种解决scheme的原因是:

  • (可以说)是丑陋的
  • 它有一个明显的开销。
  • 作为另一个答案certificate,还有其他select

但是,在以下情况下,它确实有用:

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

    • 使用null (或等价)不是一个选项(请参阅DiegoDD的评论 )
    • 你不想去关联或者用func_num_args()
    • 你的生活取决于节省一些LOC

关于性能,一个非常简单的testing表明,使用Reflection API来获取默认参数会使函数调用速度减慢25倍 ,但仍然不到1微秒 。 你应该知道你是否可以忍受。

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

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

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

那么你可以打电话给foo:

 foo("blah", "test"); 

这将导致:

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

你不能直接这样做,但有一点小小的代码可以模仿。

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

这种情况下,当对象更好 – 因为你可以设置你的对象来保存X和Y,设置默认等。

与数组的方法是靠近创build对象(实际上,对象是一堆参数和函数,将对象的工作,function采取arrays将工作一些束ov参数)

Cerainly你总是可以做一些技巧来设置null或类似的东西默认情况下

你也可以检查你是否有一个空string作为参数,所以你可以这样调用:

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

function下面:

 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! } 

如果你填空或"" ,没关系,你仍然会得到相同的结果。