【问题标题】:PHP Function with Optional Parameters带有可选参数的 PHP 函数
【发布时间】:2011-04-28 02:15:46
【问题描述】:

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

我的一个想法是传递一个带有参数数组的抽象函数,然后将其传递给真正的函数。

有没有更好的方法来设置函数,这样我就可以只传入我想要的参数?

【问题讨论】:

标签: php function parameter-passing


【解决方案1】:

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

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

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

【讨论】:

  • 对于你的例子,$optional 不需要在函数中设置为全局的吗?
  • 全球?不..?在调用函数之前创建该数组,然后传递它。我的代码是 Matt Balls 描述应该做什么的示例。
  • 除了“使用数组”的建议之外,还有更多的工作可以做——看看 Walf 对a similar question 的回答以及同一线程中更深入的示例
【解决方案2】:

让函数接受一个参数:一个数组。将实际参数作为数组中的值传入。


编辑:the link in Pekka's comment 只是总结了一下。

【讨论】:

  • 这很奇怪。 php 中的内置函数可能具有可选参数。那么为什么我们不能构建这样的函数呢?
  • @Rodrigo 定义这样的函数是绝对可行的。虽然它们是位置可选的,但对于单个可选参数之外的任何东西来说都是非常糟糕的。
  • 好的,我正在尝试使用 [ ],现在我可以在这里看到如何操作了:stackoverflow.com/a/34869/1086511
  • 除了“使用数组”的建议之外,还有更多工作要做——看看 Walf 对a similar question 的回答以及同一个线程中更深入的示例
【解决方案3】:

要完成您想要的,请使用数组Like Rabbot said(尽管如果过度使用这可能会成为记录/维护的痛苦)。或者只使用传统的可选参数。

//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 年,“代码异味”、“重构”或“代码维护”等概念在我们的社区中并不流行。你比我们大多数人先一步:)
【解决方案4】:

您可以将默认值设置为 null。

<?php
function functionName($value, $value2 = null) {
// do stuff
}

【讨论】:

  • 最佳答案,但请将null替换为日期类型的非位。例如 array() 用于数组
【解决方案5】:

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

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

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

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

上面的例子会输出:

10

Variable-length argument lists PHP Documentation

【讨论】:

  • 这个回复值得加分。不适合我的具体情况,但信息很好且易于理解。 PHP 7.3 即将推出! 5.6 和 7 已停产。
【解决方案6】:

注意:这是一个旧答案,适用于 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";
}

我更喜欢第二种方法,因为它简洁易懂,但有时您可能需要第一种方法。

【讨论】:

  • 这里需要双“=”,否则所有表达式都将返回 true。此外,第二个示例中的表达式将始终返回 true,因为变量始终等于自身。
  • 好点,但这确实有效。在 PHP 中,此代码 $x = null; if ($x) echo "true"; else echo "false"; 将打印“false”,即使 $x var 具有值(此代码中为“null”)。此外,在这两种方法中,我们都使用三元运算符,因此只使用一个“=”是正确的。如果您使用method(); method(1); method(1, 2); 进行测试,那么第一次调用会将 arg1 和 arg2 与默认值相关联,第二次调用会将第二个 arg 与默认值相关联,并且第一个 arg 为“1”。最后一次调用不会关联默认值。
  • function method_2($arg1 = "default_value_fot_arg1", $arg2 = "default_value_fot_arg2") { 所以php处理参数的东西,你也可以传递null作为参数(为什么人们使用null我不知道)
  • @nerkn,你说得对,PHP 目前支持默认参数。大声笑,我记得当我们需要做很多变通方法来实现简单的事情时。好时光:P 不过,您仍然可以在旧代码(5.5 之前)中看到这些方法。
【解决方案7】:

PHP 8开始你可以使用named arguments

function namedParameters($paramOne, $paramTwo, $paramThree = 'test', $paramFour = null)
{
    dd($paramOne, $paramTwo, $paramThree, $paramFour);
}

我们现在可以使用required 参数和可选参数调用此函数,我们希望与我们在函数中指定的default 值不同。

namedParameters('one', 'two', paramFour: 'four');

结果:

// "one", "two", "test", "four"

【讨论】:

    【解决方案8】:

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

    $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']."!";
    }
    

    【讨论】:

      【解决方案9】:

      如果创建具有有效状态的对象只需要两个值,您可以简单地删除所有其他可选参数并为它们提供设置器(除非您不希望它们在运行时更改)。然后只需使用两个必需的参数实例化对象,并根据需要通过 setter 设置其他参数。

      进一步阅读

      【讨论】:

        【解决方案10】:

        我知道这是一篇旧帖子,但我遇到了像 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);
        

        【讨论】:

          【解决方案11】:
          function yourFunction($var1, $var2, $optional = Null){
             ... code
          }
          

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

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

          【讨论】:

          • 你能进一步解释一下吗?给定的代码在语法上无效,因为变量名不能以数字开头
          【解决方案12】:

          如果您通常只传入第 8 个值,则可以重新排序参数,使其位于第一个。您只需要指定参数,直到您要设置的最后一个参数。

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

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

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

          【讨论】:

            【解决方案13】:

            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; 等,您将看到调用例如yourFunction(3, 2, $arg8=5); 将打印32 this is arg3: 5。问题是参数位置在传递时仍然很重要PHP中的可选参数...参数名称不足以将参数值映射到参数名称。
            【解决方案14】:

            只需设置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" );
            

            【讨论】:

              【解决方案15】:
              func( "1", "2", default, default, default, default, default, "eight" );
              

              【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-06-13
              • 2020-12-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-09-27
              • 1970-01-01
              相关资源
              最近更新 更多