【问题标题】:pass value for last default parameter of function传递函数最后一个默认参数的值
【发布时间】:2018-07-20 15:46:15
【问题描述】:

我在很长一段时间内都在研究 php。

但是有一个问题我可能不知道

就像我有一个功能如下:

function hello($param1, $param2="2", $param3="3", $param4="4")

现在每当我使用这个函数时,如果我需要第 4 个参数,那就是 $param4,那么我仍然需要像这样将所有参数都调用为空白:

hello(1, '', '', "param4");

那么有没有其他方法可以在调用中传递第一个和第四个参数而不是一长串空白?

或者还有其他标准方法吗?

【问题讨论】:

标签: php


【解决方案1】:

有一个名为 skipparams 的 RFC,但被拒绝了。

PHP 没有用于在调用函数时跳过可选参数的语法糖,例如 hello(1, , , "param4");hello(1, default, default, "param4");(根据 RFC)。

如果这是您自己的函数,那么您可以选择常见的 jQuery 样式,将选项传递给插件,如下所示:

function hello( $param1, $more_params = [] )
{
    static $default_params = [
        'param2' => '2',
        'param3' => '3',
        'param4' => '4'
    ];

    $more_params = array_merge( $default_params, $more_params );
}

现在你可以:

hello( 1, [ 'param4'=>'not 4, muahaha!' ] );

如果您的函数需要一些高级的东西,例如类型提示,那么您将需要手动循环 array_merge() 而不是 $more_params 并强制执行类型。

【讨论】:

  • 问题在于它没有检查 - 如果我搞砸并使用 hello( 1, [ 'parm4'=>'not 4, muahaha!' ] );
【解决方案2】:

您可以这样做的一种潜在方法,虽然有点老套,但在某些情况下可能会很好。

不要传递多个变量,而是传递一个数组变量,并在函数内部检查特定键是否存在。

function hello($param1, $variables = ["param2" => "2", "param3" => "3", "param4" => "4"]) {
    if(!array_key_exists("param2", $variables)) $variables['param2'] = "2";
    if(!array_key_exists("param3", $variables)) $variables['param3'] = "3";
    if(!array_key_exists("param4", $variables)) $variables['param4'] = "4";

    echo "<pre>".print_r($variables, true)."</pre>";
}

这将允许您在上述变量中​​设置“param4”,同时仍保留所有其他变量的默认值。

以这种方式调用函数:

hello("test", ["param4" => "filling in variable 4"]);

将导致输出为:

Array
(
    [param4] => filling in variable 4
    [param2] => 2
    [param3] => 3
)

如果可以避免,我一般不建议这样做,但如果您绝对需要此功能,这可能对您有用。

这里的关键是你在被传递的数组中有一个特别命名的索引,你可以在函数本身内部检查它。

【讨论】:

    【解决方案3】:

    在我看来,答案是肯定的和否定的。

    不,因为没有办法以标准方式执行此操作。

    是的,因为您可以绕过它。这是 hacky,但它有效;)

    例子:

    function some_call($parm1, $parm2='', $parm3='', $parm4='') { ... }
    

    还有酱汁:

    function some_call_4($parm1, $parm4) {
        return some_call($parm1, '', '', $parm4);
    }
    

    因此,如果您经常打这个电话并且厌倦了打字,您可以绕过它。

    对不起,这就是我给你的全部。

    【讨论】:

      【解决方案4】:

      这是一个开销,但您可以使用ReflectionFunction 创建一个类,该类的实例可以通过命名参数调用:

      final class FunctionWithNamedParams
      {
          private $func;
      
          public function __construct($func)
          {
              $this->func = $func;
          }
      
          public function __invoke($params = [])
          {
              return ($this->func)(...$this->resolveParams($params));
          }
      
          private function resolveParams($params)
          {
              $rf = new ReflectionFunction($this->func);
      
              return array_reduce(
                  $rf->getParameters(),
                  function ($carry, $param) use ($params) {
                      if (isset($params[$param->getName()])) {
                          $carry[] = $params[$param->getName()];
                      } else if ($param->isDefaultValueAvailable()) {
                          $carry[] = $param->getDefaultValue();
                      } else {
                          throw new BadFunctionCallException;
                      }
      
                      return $carry;
                  },  
                  []
              );
          }
      }
      

      那么你可以这样使用它:

      function hello($param1, $param2 = "2", $param3 = "3", $param4 = "4")
      {
          var_dump($param1, $param2, $param3, $param4);
      }
      
      $func = new FunctionWithNamedParams('hello');
      
      $func(['param1' => '1', 'param4' => 'foo']);
      

      这里是the demo

      【讨论】:

        猜你喜欢
        • 2012-05-22
        • 2015-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多