带有可选参数的PHP函数


107

我编写了一个PHP函数,该函数可以接受10个参数,但仅需要2个。有时,我想定义第八个参数,但是在到达第八个参数之前,我不想为每个参数键入空字符串。

我的一个想法是传递带有参数数组的抽象函数,并将其传递给实际函数。

有没有更好的方法来设置函数,以便我只能传递我想要的参数?



那很奇怪。php中的内置函数可能具有可选参数。那么为什么我们不能建立这样的功能呢?
罗德里戈

2
请注意,其中许多答案已经过时了 ... PHP现在支持带有可变长度参数列表的函数
ashleedawg,

Answers:


62

使函数采用一个参数:数组。将实际参数作为数组中的值传递。


编辑: Pekka的评论中的链接仅作总结。


1
那很奇怪。php中的内置函数可能具有可选参数。那么为什么我们不能建立这样的功能呢?
罗德里戈

1
@Rodrigo绝对可以定义这样的函数。但是它们是位置可选的,这对于除单个可选参数之外的任何东西都非常糟糕。
马特·鲍尔

1
好的,我正在尝试[],现在我在这里看到了如何做:stackoverflow.com/a/34869/1086511
Rodrigo

仅仅是“使用数组”的建议,还有很多事情可以做-看看沃尔夫对一个类似问题的答案以及更深入的例子
DJDave

63

在这种情况下,我要做的是传递一个数组,其中的键是参数名称,而值是值。

$optional = array(
  "param" => $param1,
  "param2" => $param2
);

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}

对于您的示例,是否需要在函数内将$ optional设置为全局值?
user481826

1
全球?没有..?您在调用该函数之前创建该数组,然后将其传递。我的代码是Matt Balls说明应执行的操作的示例。
拉博特(Rabbott)2010年

除了“使用数组”建议外,还有很多事情可以做-看看沃尔夫对一个类似问题的答案以及更深入的例子
DJDave

45

要完成所需的操作,请使用Rabbot所说的数组(但是如果使用过多,这可能会很难记录/维护)。或者只使用传统的可选参数。

//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
  //Do stuff
}
my_func('Hi', 'World', null, null, 'Red');

但是,我通常会发现,当我开始编写具有这么多参数的函数/方法时-通常不是代码异味,并且可以将其重构/抽象为更整洁的东西。

//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
  return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');

在2010年,“代码气味”,“重构”或“代码维护”等概念在我们的社区中并不流行。您在我们大多数人之前已经迈出了一步:)
Billal Begueradj

15

在PHP 5.6和更高版本中,参数列表可能包含...令牌,以表示该函数接受可变数量的参数。参数将作为数组传递到给定变量中;例如:

使用...访问变量参数的示例

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

上面的示例将输出:

10

变长参数列表PHP文档


这个回应值得更多的分数。不适合我的特定情况,但信息丰富且易于理解。PHP 7.3即将发布!5.6和7是EOL。
AdheneManx


12

注意:这是旧的答案,适用于PHP 5.5及以下版本。PHP 5.6+支持默认参数

在PHP 5.5及更低版本中,您可以使用以下两种方法之一来实现此目的:

  • 使用func_num_args()func_get_arg()函数;
  • 使用NULL参数;

如何使用

function method_1()
{
  $arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
  $arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}

function method_2($arg1 = null, $arg2 = null)
{
  $arg1 = $arg1? $arg1: "default_value_for_arg1";
  $arg2 = $arg2? $arg2: "default_value_for_arg2";
}

我喜欢第二种方法,因为它很干净而且易于理解,但是有时您可能需要第一种方法。


1
您需要在此处使用双“ =”,否则所有表达式都将返回true。同样,第二个示例中的表达式将始终返回true,因为变量始终等于其自身。
chuckieDub

好点,但这确实有效。在PHP中$x = null; if ($x) echo "true"; else echo "false";,即使$ x var具有值(此代码中为“ null”),该代码也会显示“ false”。另外,在这两种方法中,我们都使用三元运算符,因此仅使用一个“ =”是正确的。如果使用进行测试method(); method(1); method(1, 2);,则第一个调用会将arg1和arg2与默认值相关联,第二个调用会将第二个arg与默认值相关联,而第一个arg则与“ 1”相关联。最后一次调用不会关联默认值。
Daniel Loureiro

1
函数method_2($ arg1 =“ default_value_fot_arg1”,$ arg2 =“ default_value_fot_arg2”){因此php处理参数内容,并且您也可以将null用作参数(为什么人们使用null我不知道)
nerkn

1
@nerkn,您是对的,PHP当前支持默认参数。大声笑,我记得当我们需要采取很多变通办法来实现简单的事情时。好的时机:P但是,您仍然可以在旧代码(5.5之前)中看到这些方法。
Daniel Loureiro

4

我认为,您也可以将对象用作参数传输。

$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);

function theFunction($fparam){      
  return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}

当然,您必须在此函数中为“ optParam8”和“ optParam2”设置默认值,否则,您将获得“ Notice:Undefined property:stdClass :: $ optParam2”

如果使用数组作为函数参数,我喜欢这种方式来设置默认值:

function theFunction($fparam){
   $default = array(
      'opt1' => 'nothing',
      'opt2' => 1
   );
   if(is_array($fparam)){
      $fparam = array_merge($default, $fparam);
   }else{
      $fparam = $default;
   }
   //now, the default values are overwritten by these passed by $fparam
   return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}


2

我知道这是一篇旧文章,但是我遇到了像OP这样的问题,这就是我想出的。

您可以通过的数组示例。如果需要特定的订单,可以重新订购,但是对于这个问题,它将按照要求进行。

$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');

这是易于管理的,易于阅读的,并且可以在编码中的任何位置立即添加和删除数据提取点,并且仍然避免大量重写。我使用整数键来计算OP原始问题,但是可以很容易地使用字符串键。实际上,出于可读性考虑,我会建议这样做。

轻松粘贴到外部文件中

function unknown_number_arguments($argument_set) {

    foreach ($argument_set as $key => $value) {

        # create a switch with all the cases you need. as you loop the array 
        # keys only your submitted $keys values will be found with the switch. 
        switch ($key) {
            case 1:
                # do stuff with $value
                break;
            case 2:
                # do stuff with $value;
                break;
            case 3:
                # key 3 omitted, this wont execute 
                break;
            case 5:
                # do stuff with $value;
                break;
            case 8:
                # do stuff with $value;
                break;
            default:
                # no match from the array, do error logging?
                break;
        }
    }
return;
}

如果是文件,则将其放在开头。

$argument_set = array(); 

只需使用这些来根据数据来自何处分配下一个数据使用编号/命名。

$argument_set[1][] = $some_variable; 

最后传递数组

unknown_number_arguments($argument_set);

1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

您可以创建一个常规函数,然后通过为它们提供默认的Null值来添加可选变量。

Null仍然是一个值,如果不使用该变量的值调用该函数,则该值不会为空,因此不会出错。


2
您能进一步解释所有这些吗?给定的代码在语法上无效,因为变量名不能以数字开头
Nico Haase

0

如果通常只传递第8个值,则可以重新排列参数,因此它是第一个。您只需要指定参数,直到最后一个要设置的参数即可。

如果使用不同的值,则有2个选项。

一种方法是创建一组包装函数,这些包装函数采用不同的参数,并在其他包装函数上设置默认值。如果您仅使用一些组合,但很快就会变得非常混乱,这很有用。

另一种选择是传递一个数组,其中键是参数的名称。然后,您可以只检查数组中是否有带键的值,如果不使用默认值。但是同样,如果您有很多参数,这可能会变得混乱并添加很多额外的代码。


0

PHP允许使用默认参数(link)。在您的情况下,您可以根据功能代码将3到8的所有参数定义为NULL或为空字符串“”。这样,您只能使用前两个参数来调用该函数。

例如:

<?php
  function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}

有趣的主意...但是您的建议无法解决问题。实际上,如果您添加有关正在回显什么参数的信息(例如,通过使用echo " this is arg3: " . $arg3;等),您将看到调用eg yourFunction(3, 2, $arg8=5);将进行打印32 this is arg3: 5。问题在于,当在PHP中传递可选参数时,参数位置仍然很重要...参数名称是不够的,以参数值映射到参数名称。
mastropi

0

只需将Null设置为忽略不需要的参数,然后根据位置设置所需的参数即可。

 function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
    for ($i=1; $i<9; $i++){
        $varName = "p$i";
        if (isset($$varName)){
            echo $varName." = ".$$varName."<br>\n";
        }
    }
}   

myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.