Yii2 ActiveRecord 建议在自己的逻辑之后调用父构造函数。这不奇怪吗?

Yii2 ActiveRecord recommends to call parent constructor after own logic. Isn't this strange?

我是 Yii2 的新手,很长一段时间后又回到 PHP 开发。我在 Java 开发方面有广泛的背景。我在 docs for ActiveRecord:

中偶然发现了这个建议

__construct() public method

Defined in: yii\base\BaseObject::__construct()

Constructor.

The default implementation does two things:

  • Initializes the object with the given configuration $config.
  • Call init().

If this method is overridden in a child class, it is recommended that

  • the last parameter of the constructor is a configuration array, like $config here.
  • call the parent implementation at the end of the constructor.

我的问题是最后一句:

call the parent implementation at the end of the constructor.

作为一名 Java 开发者,这个建议对我来说似乎很奇怪。在 Java 中,不仅建议在重写构造函数的第一个调用中调用父构造函数,这甚至是强制执行的,实际上不可能以任何其他方式进行。您的父构造函数首先被隐式调用,或者,如果您进行显式调用,它必须是您方法中的第一个语句。这是由编译器强制执行的。

从理论上讲,这对我来说很有意义。因为只要你不调用父构造函数,你的父 class 就没有机会初始化,所以你在调用父构造函数之前在构造函数中编写的任何代码都将使用半初始化对象。

查看我发现的一些 SO 答案,他们似乎违背了官方文档中的建议,并在他们自己的自定义逻辑之前调用 parent::__construct,正如我所期望的那样。例如, in the question 显示了他们首先调用父级的示例:

function __construct()
{
    parent::__construct();
    ...
}

在遵循官方文档建议的同一个问题中得 0 分:

    public function __construct($config = []) {
         // your init code here
         // ...
         parent::__construct();
    }

查看 phptutorial.net 上的 the article about calling the parent constructor,他们展示了一个示例,其中他们首先调用父级,正如我所期望的那样:

class SavingAccount extends BankAccount
{
    private $interestRate;

    public function __construct($balance, $interestRate)
    {
        parent::__construct($balance);

        $this->interestRate = $interestRate;
    }

    // ...
}

正如我所说,我的 PHP 很生疏,我是 Yii2 n00b,所以我希望在这里得到一些关于这个非常基本的东西的澄清,在阅读文档和教程后我仍然不清楚SO 现在发帖几个小时了。这项调查是由于看到构造函数在我继承的和当前正在处理的代码库中第一次和最后一次被调用非常不一致而引发的。

在PHP中,是否有关于何时调用父构造函数的官方建议?

在其他 PHP 框架中是否也建议最后调用父构造函数?

希望不要煽动观点讨论,所以请引用官方参考资料,指向其他项目的官方文档等

@michal-hynčica 正确说明了你歧义的原因(值得 votUp)。
但是既然你提到了官方参考,关于同一页 (BaseObject), this issue is explicitly stated: line

  • In order to ensure the above life cycles, if a child class of BaseObject needs to override the constructor,
  • ....
  • of the constructor, and the parent implementation should be called at the end of the constructor.

根据这个的描述(类似于你的问题):
init() 被调用进一步调用 bootstrap() 到 运行 bootstrapping 组件。
因此,这样做是为了确保配置。 在 controller class 和主模块中完成相同的过程。
当然,php网站上有很多这样的例子(根据需要) 另请阅读 lifecycles and entry script in yii. components and structure-applications。祝你好运