在PHP中指定可选参数值的任何方法?

时间:2009-03-27 17:00:00

标签: php function optional-parameters

假设我有一个PHP函数foo:

function foo($firstName = 'john', $lastName = 'doe') {
    echo $firstName . " " . $lastName;
}
// foo(); --> john doe

有没有办法只指定第二个可选参数?

示例:

foo($lastName='smith'); // output: john smith

12 个答案:

答案 0 :(得分:32)

PHP本身不支持函数的命名参数。但是,有一些方法可以解决这个问题:

  1. 使用数组作为函数的唯一参数。然后,您可以从数组中提取值。这允许在数组中使用命名参数。
  2. 如果要根据上下文允许可选数量的参数,则可以使用func_num_args和func_get_args,而不是在函数定义中指定有效参数。然后根据参数的数量,字符串长度等,您可以确定要做什么。
  3. 将空值传递给您不想指定的任何参数。不是真的绕过它,但它确实有效。
  4. 如果您正在使用对象上下文,那么您可以使用魔术方法__call()来处理这些类型的请求,以便您可以根据传递的参数路由到私有方法。

答案 1 :(得分:22)

阵列技术的一种变体,可以更容易地设置默认值:

function foo($arguments) {
  $defaults = array(
    'firstName' => 'john',
    'lastName' => 'doe',
  );

  $arguments = array_merge($defaults, $arguments);

  echo $arguments['firstName'] . ' ' . $arguments['lastName'];
}

用法:

foo(array('lastName' => 'smith')); // output: john smith

答案 2 :(得分:9)

您可以稍微重构一下代码:

function foo($firstName = NULL, $lastName = NULL)
{
    if (is_null($firstName))
    {
        $firstName = 'john';
    }
    if (is_null($lastName ))
    {
        $lastName = 'doe';
    }

    echo $firstName . " " . $lastName;
}

foo(); // john doe
foo('bill'); // bill doe
foo(NULL,'smith'); // john smith
foo('bill','smith'); // bill smith

答案 3 :(得分:6)

如果您有多个可选参数,一个解决方案是传递一个哈希数组参数:

function foo(array $params = array()) {
    echo $params['firstName'] . " " . $params['lastName'];
}

foo(array('lastName'=>'smith'));

当然,在此解决方案中,无法确认哈希数组的字段是否存在或拼写正确。完全由您来验证。

答案 4 :(得分:3)

没有。通常的方法是使用一些启发式方法来确定隐含的参数,如字符串长度,键入等。

一般来说,您可以编写函数来按照最需要的顺序获取参数。

答案 5 :(得分:3)

你想要的方式:不。

你可以使用一些特殊的标记,比如NULL,注意不提供值:

function foo($firstName, $lastName = 'doe') {
    if (is_null($firstName))
        $firstName = 'john';
    echo $firstName . " " . $lastName;
}

foo(null, 'smith');

答案 6 :(得分:2)

PHP 8 引入了命名参数,因此现在可以指定传递给函数的参数。

在 PHP 8 之前:

htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

在 PHP 8 之后:

htmlspecialchars($string, double_encode: false);

Reference

答案 7 :(得分:1)

这里提到了一些'选项'样式实现。如果您计划将它们作为标准使用,到目前为止都没有防水措施。试试这个模式:

function some_func($required_parameter, &$optional_reference_parameter = null, $options = null) {
    $options_default = array(
        'foo' => null,
    );
    extract($options ? array_intersect_key($options, $options_default) + $options_default : $options_default);
    unset($options, $options_default);

    //do stuff like
    if ($foo !== null) {
        bar();
    }
}

这为您提供了函数局部变量(在此示例中仅为$foo),并阻止创建任何没有默认值的变量。这样就不会有人意外地覆盖函数中的其他参数或其他变量。

答案 8 :(得分:1)

当我在2.5年前开始使用PHP时,我希望这个解决方案已经开始了。它在我创建的示例中运行良好,我不明白为什么它不应该是完全可扩展的。与以前提出的相比,它具有以下优点:

(i)对函数内所有参数的访问都是通过命名变量进行的,就好像参数是完全声明的,而不是要求数组访问

(ii)调整现有功能非常快捷方便

(iii)任何函数只需要一行额外的代码(除了定义你的默认参数之外不可避免的必要性,无论如何你要在函数签名中做,但是你要在数组中定义它们) )。额外线路的信用完全归功于Bill Karwin。这条线对于每个功能都是相同的。

方法

使用必需参数和可选数组

定义函数

将可选参数声明为局部变量

症结:使用通过数组传递的参数替换任何可选参数的预先声明的默认值。

extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));

调用函数,传递其必需参数,并仅传递您需要的可选参数

例如,

function test_params($a, $b, $arrOptionalParams = array()) {

$arrDefaults = array('c' => 'sat',

                     'd' => 'mat');

extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));

echo "$a $b $c on the $d";

}

然后像这样调用它

test_params('The', 'dog', array('c' => 'stood', 'd' => 'donkey'));
test_params('The', 'cat', array('d' => 'donkey'));
test_params('A', 'dog', array('c' => 'stood'));

结果:

狗站在驴上

猫坐在驴上

一只狗站在垫子上

答案 9 :(得分:0)

如果经常使用它,只需定义一个新的专用函数:

function person($firstName = 'john', $lastName = 'doe') {
    return $firstName . " " . $lastName;
}

function usualFirtNamedPerson($lastName = 'doe') {
    return person('john', $lastName);
}

print(usualFirtNamedPerson('smith')); --> john smith

请注意,如果您愿意,也可以在流程中更改$ lastname的默认值。

当估计新功能过时时,只需使用所有参数调用函数即可。如果您想更清楚,可以将文字预存在fin命名变量中或使用注释。

$firstName = 'Zeno';
$lastName = 'of Elea';
print(person($firstName, $lastName));
print(person(/* $firstName = */ 'Bertrand', /* $lastName = */ 'Russel'));

好吧,这不像person($lastName='Lennon')那么短而优雅,但似乎你不能在PHP中拥有它。这不是最性感的编码方式,超级元编程技巧或其他什么,但你更喜欢在维护过程中遇到什么解决方案?

答案 10 :(得分:-1)

没有,但你可以使用数组:

function foo ($nameArray) {
    // Work out which values are missing?
    echo $nameArray['firstName'] . " " . $nameArray['lastName'];
}

foo(array('lastName'=>'smith'));

答案 11 :(得分:-1)

可悲的是,你正在尝试做的事情没有“语法糖”的方式。它们都是各种形式的WTF。

如果需要一个带有未定义数量的任意参数的函数,

function foo () { 
     $args = func_get_args(); 
     # $args = arguments in order 
}

会做的伎俩。尽量避免使用太多,因为对于Php来说,这有点神奇。

然后,您可以选择应用默认值并根据参数计数执行奇怪的操作。

function foo(){ 
   $args = func_get_args();
   if( count($args) < 1 ){ 
       return "John Smith"; 
   }
   if( count($args) < 2 ) { 
       return "John " .$args[0];
   }
   return $args[0] . " " . $args[1];
}

此外,您可以选择模拟Perl样式参数,

function params_collect( $arglist ){ 
    $config = array();
    for( $i = 0; $i < count($arglist); $i+=2 ){ 
       $config[$i] = $config[$i+1];
    }
    return $config; 
}
function param_default( $config, $param, $default ){ 
    if( !isset( $config[$param] ) ){ 
           $config[$param] = $default;
    }
    return $config;
}

function foo(){ 
   $args = func_get_args();
   $config = params_collect( $args ); 
   $config = param_default( $config, 'firstname' , 'John' ); 
   $config = param_default( $config, 'lastname' ,  'Smith' ); 
   return $config['firstname'] . '  ' . $config['lastname'];   
}

foo( 'firstname' , 'john', 'lastname' , 'bob' ); 
foo( 'lastname' , 'bob', 'firstname', 'bob' ); 
foo( 'firstname' , 'smith'); 
foo( 'lastname', 'john' );

当然,在这里会更容易使用数组参数,但是你可以选择(甚至是糟糕的方式)做事。

值得注意的是,这在Perl中更好,因为你可以只做foo(firstname =&gt;'john');