为什么我突然得到“初始化前一定不能访问Typed属性"的原因.引入属性类型提示时出错? [英] Why I am suddenly getting a "Typed property must not be accessed before initialization" error when introducing properties type hints?

查看:1044
本文介绍了为什么我突然得到“初始化前一定不能访问Typed属性"的原因.引入属性类型提示时出错?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经更新了类定义,以利用新引入的属性类型提示,例如:

I have updated my class definitions to make use of the newly introduced property type hints, like this:

class Foo {

    private int $id;
    private ?string $val;
    private DateTimeInterface $createdAt;
    private ?DateTimeInterface $updatedAt;

    public function __construct(int $id) {
        $this->id = $id;
    }


    public function getId(): int { return $this->id; }
    public function getVal(): ?string { return $this->val; }
    public function getCreatedAt(): ?DateTimeInterface { return $this->createdAt; }
    public function getUpdatedAt(): ?DateTimeInterface { return $this->updatedAt; }

    public function setVal(?string $val) { $this->val = $val; }
    public function setCreatedAt(DateTimeInterface $date) { $this->createdAt = $date; }
    public function setUpdatedAt(DateTimeInterface $date) { $this->updatedAt = $date; }
}

但是当试图将我的实体保存在教义上时,我收到一条错误消息:

But when trying to save my entity on Doctrine I am getting an error saying:

在初始化之前不能访问Typed属性

Typed property must not be accessed before initialization

这不仅发生在$id$createdAt上,而且发生在$value$updatedAt上,它们是可为空的属性.

This not only happens with $id or $createdAt, but also happen with $value or $updatedAt, which are nullable properties.

推荐答案

由于PHP 7.4引入了属性的类型提示,因此为所有属性提供有效值特别重要,这样所有属性都具有与其声明的类型相匹配的值

Since PHP 7.4 introduces type-hinting for properties, it is particularly important to provide valid values for all properties, so that all properties have values that match their declared types.

从未分配的变量没有null值,但处于undefined状态,将永远不与任何声明的类型匹配. undefined !== null.

A variable that has never been assigned doesn't have a null value, but it is on an undefined state, which will never match any declared type. undefined !== null.

对于上面的代码,如果您这样做:

For the code above, if you did:

$f = new Foo(1);
$f->getVal();

您会得到:

致命错误:未捕获错误:初始化前不得访问类型为Foo :: $ val的属性

Fatal error: Uncaught Error: Typed property Foo::$val must not be accessed before initialization

由于$val在访问时既不是string也不是null.

Since $val is neither string nor nullwhen accessing it.

解决此问题的方法是将值分配给与声明的类型匹配的所有属性.您可以将其作为属性的默认值,也可以在构造过程中根据您的喜好和属性的类型进行设置.

The way to get around this is to assign values to all your properties that match the declared types. You can do this either as default values for the property or during construction, depending on your preference and the type of the property.

例如,对于上述一种情况,可以做到:

For example, for the above one could do:

class Foo {

    private int $id;
    private ?string $val = null; // <-- declaring default null value for the property
    private DateTimeInterface $createdAt;
    private ?DateTimeInterface $updatedAt;

    public function __construct(int $id) {
        // and on the constructor we set the default values for all the other 
        // properties, so now the instance is on a valid state
        $this->id = $id;
        $this->createdAt = new DateTimeImmutable();
        $this->updatedAt = new DateTimeImmutable();
    }

现在,所有属性都将具有 valid 值,并且实例将处于有效状态.

Now all properties would have a valid value and the the instance would be on a valid state.

当您依赖数据库中的值作为实体值时,这种情况尤其常见.例如.自动生成的ID,或创建和/或更新的值;这通常是数据库问题.

This can hit particularly often when you are relying on values that come from the DB for entity values. E.g. auto-generated IDs, or creation and/or updated values; which often are left as a DB concern.

对于自动生成的ID,推荐的转发方式是将类型声明更改为?int $id = null.对于其余所有属性,只需为属性的类型选择一个合适的值即可.

For auto-generated IDs, the recommended way forward is to change the type declaration to ?int $id = null. For all the rest, just choose an appropriate value for the property's type.

这篇关于为什么我突然得到“初始化前一定不能访问Typed属性"的原因.引入属性类型提示时出错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆