带有可选参数的 PHP 函数

Posted

技术标签:

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

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

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

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

【问题讨论】:

相关:***.com/questions/2112913 这很奇怪。 php 中的内置函数可能具有可选参数。那么为什么我们不能构建这样的函数呢? 请注意,其中许多答案已过时... PHP 现在支持 functions with variable-length argument lists 【参考方案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 定义这样的函数是绝对可行的。虽然它们是位置可选的,但对于单个可选参数之外的任何东西来说都是非常糟糕的。 好的,我正在尝试使用 [ ],现在我可以在这里看到如何操作了:***.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 设置其他参数。

进一步阅读

Martin Fowler on Constructor vs Setter Injection 和 Dependency injection through constructors or property setters?

【讨论】:

【参考方案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" );

【讨论】:

这不是有效的 PHP。 default 是 keyword in PHP。

以上是关于带有可选参数的 PHP 函数的主要内容,如果未能解决你的问题,请参考以下文章

PHP函数中的可选参数不考虑顺序

带有可选参数的 Postgresql 函数

如何为带有可选参数的函数编写测试

Bash - 带有可选参数和缺少逻辑的函数

使用 PyObject_CallMethod 调用带有可选参数的函数

通过反射调用带有可选参数的方法