有什么方法可以在 PHP 中指定可选参数值吗?

发布于 2024-07-16 08:43:34 字数 284 浏览 9 评论 0原文

假设我有一个 PHP 函数 foo:

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

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

例子:

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

Let's say I've got a PHP function foo:

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

Is there any way to specify only the second optional parameter?

Example:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

星星的軌跡 2024-07-23 08:43:34

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

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

PHP does not support named parameters for functions per se. However, there are some ways to get around this:

  1. Use an array as the only argument for the function. Then you can pull values from the array. This allows for using named arguments in the array.
  2. If you want to allow optional number of arguments depending on context, then you can use func_num_args and func_get_args rather than specifying the valid parameters in the function definition. Then based on number of arguments, string lengths, etc you can determine what to do.
  3. Pass a null value to any argument you don't want to specify. Not really getting around it, but it works.
  4. If you're working in an object context, then you can use the magic method __call() to handle these types of requests so that you can route to private methods based on what arguments have been passed.
简单气质女生网名 2024-07-23 08:43:34

数组技术的一种变体,可以更轻松地设置默认值:

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

A variation on the array technique that allows for easier setting of default values:

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

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

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

Usage:

foo(array('lastName' => 'smith')); // output: john smith
暮年 2024-07-23 08:43:34

您可以稍微重构您的代码:

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

You could refactor your code slightly:

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
好久不见√ 2024-07-23 08:43:34

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

function foo(array $params = array()) {
    $firstName = array_key_exists("firstName", $params) ?
      $params["firstName"] : "";
    $lastName = array_key_exists("lastName", $params) ?
      $params["lastName"] : "";
    echo $firstName . " " . $lastName;
}

foo(['lastName'=>'smith']);

当然,在此解决方案中,不会验证哈希数组的字段是否存在或拼写是否正确。 这一切都由你来验证。

If you have multiple optional parameters, one solution is to pass a single parameter that is a hash-array:

function foo(array $params = array()) {
    $firstName = array_key_exists("firstName", $params) ?
      $params["firstName"] : "";
    $lastName = array_key_exists("lastName", $params) ?
      $params["lastName"] : "";
    echo $firstName . " " . $lastName;
}

foo(['lastName'=>'smith']);

Of course in this solution there's no validation that the fields of the hash array are present, or spelled correctly. It's all up to you to validate.

司马昭之心 2024-07-23 08:43:34

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

PHP 8 之前:

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

PHP 8 之后:

htmlspecialchars($string, double_encode: false);

参考

PHP 8 introduced named arguments so now it's possible to specify the parameters passed to a function.

before PHP 8:

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

after PHP 8:

htmlspecialchars($string, double_encode: false);

Reference

闻呓 2024-07-23 08:43:34

不。通常的方法是使用一些启发式方法来确定隐含的参数,例如字符串长度、类型等。

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

No. The usual way of doing this is with some heuristics to determine which parameter was implied, like string length, typing, etc.

Generally speaking, you'd write the function to take the parameters in the order of most required to least required.

御守 2024-07-23 08:43:34

你想要的方式:不。

您可以使用一些特殊标记,例如 NULL 来指出未提供值:

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

foo(null, 'smith');

The way you want: no.

You could use some special mark, like NULL to note that value is not supplied:

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

foo(null, 'smith');
感性不性感 2024-07-23 08:43:34

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

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

(ii)它可以非常快速且轻松地适应现有的函数

(iii) 任何函数都只需要一行附加代码(除了不可避免地需要定义默认参数之外,您无论如何都会在函数签名中执行此操作,但您可以在数组中定义它们)。 额外线路的功劳完全归功于比尔·卡尔文。 该行对于每个函数都是相同的。

方法

使用强制参数和可选数组定义函数

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

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

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'));

结果:

狗站在驴上

猫坐在驴上

狗站在垫子上

I wish this solution had been on SO when I started using PHP 2.5 years ago. It works great in the examples I have created, and I don't see why it shouldn't be thoroughly extensible. It offers the following benefits over those proposed previously:

(i) all access to parameters within the function is by named variables, as if the parameters were fully declared, rather than requiring array access

(ii) it is very quick and easy to adapt existing functions

(iii) only a single line of additional code is required for any function (in addition to the inescapable necessity of defining your default parameters, which you would be doing in the function signature anyway, but instead you define them in an array). Credit for the additional line is wholly due to Bill Karwin. This line is identical for every function.

Method

Define your function with its mandatory parameters, and an optional array

Declare your optional parameters as local variables

The crux: replace the pre-declared default value of any optional parameters using those you have passed via the array.

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

Call the function, passing its mandatory parameters, and only those optional parameters that you require

For example,

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";

}

and then call it like this

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

Results:

The dog stood on the donkey

The cat sat on the donkey

A dog stood on the mat

酒几许 2024-07-23 08:43:34

这里提到了一些“选项”风格的实现。 如果您打算将它们作为标准使用,那么到目前为止,没有一个是非常防弹的。 尝试这种模式:

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),并防止创建任何没有默认值的变量。 这样一来,任何人都不会意外地覆盖函数内的其他参数或其他变量。

There are a few 'options' style implementations mentioned here. None thus far are very bulletproof if you plan to use them as as standard. Try this pattern:

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();
    }
}

This gives you function-local variables (just $foo in this example) and prevents creating any variables that do not have a default. This is so no one can accidentally overwrite other parameters or other variables within the function.

小苏打饼 2024-07-23 08:43:34

参数需要按位置顺序传递,您不能跳过参数本身; 您必须提供默认参数值才能跳过它。 可以说,这违背了您想要实现的目的。

无需重写函数以不同方式接受参数,这里有一种调用时方法来解决此问题:

$func = 'foo';
$args = ['lastName' => 'Smith'];

$ref = new ReflectionFunction($func);
$ref->invokeArgs(array_map(function (ReflectionParameter $param) use ($args) {
    if (array_key_exists($param->getName(), $args)) {
        return $args[$param->getName()];
    }
    if ($param->isOptional()) {
        return $param->getDefaultValue();
    }
    throw new InvalidArgumentException("{$param->getName()} is not optional");
}, $ref->getParameters()));

换句话说,您使用反射来检查函数的参数并按名称将它们映射到可用参数,并跳过可选参数及其默认值价值。 是的,这很丑陋而且很麻烦。 您可以使用此示例创建一个如下函数:

call_func_with_args_by_name('foo', ['lastName' => 'Smith']);

Arguments need to be passed in order by position, you cannot skip a parameter per se; you'll have to supply the default parameter value in order to skip it. Arguably that defeats the purpose of what you're trying to achieve.

Without rewriting your function to accept parameters differently, here's a call-time way to work around this:

$func = 'foo';
$args = ['lastName' => 'Smith'];

$ref = new ReflectionFunction($func);
$ref->invokeArgs(array_map(function (ReflectionParameter $param) use ($args) {
    if (array_key_exists($param->getName(), $args)) {
        return $args[$param->getName()];
    }
    if ($param->isOptional()) {
        return $param->getDefaultValue();
    }
    throw new InvalidArgumentException("{$param->getName()} is not optional");
}, $ref->getParameters()));

In other words, you're using reflection to inspect the function's parameters and map them to the available parameters by name, skipping optional parameters with their default value. Yes, this is ugly and cumbersome. You could use this sample to create a function like:

call_func_with_args_by_name('foo', ['lastName' => 'Smith']);
魄砕の薆 2024-07-23 08:43:34

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

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 中拥有它。 这并不是最性感的编码方式,使用超级元编程技巧或其他什么,但是您希望在维护过程中遇到什么解决方案?

If this is used very often, just define a new specialized function :

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

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

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

Note that you could also change the default value of $lastname in the process if you wish.

When a new function is estimated overbloated, just call you function with all parameters. If you want to make it more clear, you can prestore your literals in fin named variable or use comments.

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

Ok, this is not as short and elegant as person($lastName='Lennon'), but it seems you can't have it in PHP. And that's not the sexiest way to code it, with super metaprogramming trick or whatever, but what solution would you prefer to encounter in a maintenance process?

晨曦÷微暖 2024-07-23 08:43:34

遗憾的是,您想要做的事情没有“语法糖”的方式来实现。 它们都是 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 => 'john' );

Sadly what you're trying to do has no "syntactic sugar" way of doing it. They're all varying forms of WTF.

If you need a function that takes an undefined number of arbitrary parameters,

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

Will do the trick. Try avoid using it too much, because for Php this is a bit on the magical side.

You could then optionally apply defaults and do strange things based on parameter count.

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];
}

Also, you could optionally emulate Perl style parameters,

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');

Of course, it would be easier to use an array argument here, but you're permitted to have choice ( even bad ways ) of doing things.

notedly, this is nicer in Perl because you can do just foo( firstname => 'john' );

梦里南柯 2024-07-23 08:43:34

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

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

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

No there isn't but you could use an array:

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

foo(array('lastName'=>'smith'));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文