【问题标题】:What am I doing wrong with my optional PHP arguments?我的可选 PHP 参数做错了什么?
【发布时间】:2018-06-20 18:17:24
【问题描述】:

我有以下课程:

class MyClass {

    public function __construct($id = 0, $humanIdentifier = '') {
        $this->id = $id;
        $this->humanID = $humanIdentifier;
    }
}

所以根据我的解释,如果我愿意,我应该能够将 $id 或 $humanIdentifier 传递给该构造函数,或者两者都传递。但是,当我调用下面的代码时,我发现它的构造函数参数中的 $id 设置为 hello world 而不是 $humanIdentifier,尽管我在调用构造函数时指定了 $humanIdentifier。谁能看出我哪里出错了?

$o = new MyClass($humanIdentifier='hello world');

【问题讨论】:

  • 这将被解释为将 'hello world' 分配给名为 $humanIdentifier 的变量,然后将此值作为第一个参数 ($id) 传递给您的构造函数。

标签: php class constructor


【解决方案1】:

编辑:从 PHP8 开始,现在支持命名参数。在本文发布时并非如此。

PHP 不支持命名参数,它会根据你传递参数的顺序来设置值。

在您的情况下,您没有传递$humanIdentifier,而是表达式$humanIdentifier='hello world' 的结果,$this->id 稍后将设置为。

我知道在 PHP 中模仿命名参数的唯一方法是数组。所以你可以这样做(在 PHP7 中):

public function __construct(array $config)
{
    $this->id = $config['id'] ?? 0;
    $this->humanId = $config['humanId'] ?? '';
}

【讨论】:

  • 那太好了,谢谢,我习惯使用 Python 并且有一段时间没有使用 PHP。
  • 更新:PHP8 现在支持命名参数。
【解决方案2】:

就像另一个答案所说,php 不支持命名参数。您可以通过以下方式完成类似的操作:

class MyClass {

  public function __construct($args = array('id' => 0, 'humanIdentifier' => '') {.
    // some conditional logic to emulate the default values concept
    if(!isset($args['id'])){
      $this->id = 0;
    }else{
      $this->id = $args['id'];
    }
    if(!isset($args['humanIdentifier'])){
      $this->humanID = '';
    }else{
      $this->humanID = $args['humanIdentifier'];
    }
  }
}

你可以这样称呼它:

new MyClass(array('humanIdentifier'=>'hello world'));

默认的id 将在那里。如果有足够的参数值得一试,我相信你可以想出一些花哨的迭代来完成这个。

【讨论】:

    【解决方案3】:

    您需要重载构造函数,但 php 没有内置功能,但文档中有一个很好的解决方法:

    http://php.net/manual/en/language.oop5.decon.php#Hcom99903

    还有一个讨论为什么它可能是一个坏主意:Why can't I overload constructors in PHP?

    【讨论】:

      【解决方案4】:

      你不能通过这种方式创建新的类对象:

          $o = new MyClass($humanIdentifier='hello world');
      

      你可以使用数组作为__construct的参数:

      class MyClass {
      
          public function __construct(array $arg) {
              $this->id = isset($arg['id']) ? $arg['id'] : 0;
              $this->humanID = isset($arg['humanID']) ? $arg['humanID'] : 0;
          }
      }
      

      然后你可以通过这种方式创建新的类对象:

      $o = new MyClass(['humanId'=>hello world']);
      

      【讨论】:

        【解决方案5】:

        谁能看出我哪里出错了?

        是的,您认为这些是命名参数。他们不是。它们是位置参数。所以你可以这样称呼它:

        new MyClass(0, 'hello world')
        

        已建议添加对命名参数的支持,过去是 rejected。较新的 RFC is proposed,但仍有待完善和实施。

        【讨论】:

          猜你喜欢
          • 2011-11-03
          • 2010-10-23
          • 1970-01-01
          • 2019-11-13
          • 2018-12-31
          • 1970-01-01
          • 1970-01-01
          • 2011-06-01
          • 1970-01-01
          相关资源
          最近更新 更多