php - 为什么我在引入属性类型提示时突然收到 "Typed property must not be accessed before initialization"错误?

标签 php doctrine-orm php-7 type-hinting php-7.4

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

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

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

Typed property must not be accessed before initialization



这不仅发生在 $id$createdAt ,但也会发生在 $value$updatedAt ,它们是可为空的属性。

最佳答案

由于 PHP 7.4 为属性引入了类型提示,因此为所有属性提供有效值尤为重要,以便所有属性都具有与其声明类型匹配的值。
从未分配过的属性没有 null值,但它在 undefined 上状态,它永远不会匹配任何声明的类型 . undefined !== null .
对于上面的代码,如果你这样做了:

$f = new Foo(1);
$f->getVal();
你会得到:

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


$val两者都不是 string也不是 null访问它时。
解决这个问题的方法是为所有与声明类型匹配的属性赋值。您可以将其作为属性的默认值或在构建期间执行此操作,具体取决于您的偏好和属性类型。
例如,对于上面的一个可以这样做:
class Foo {

    private int $id;
    private ?string $val = null; // <-- declaring default null value for the property
    private Collection $collection;
    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();

        $this->collection = new ArrayCollection();
    }
现在所有的属性都会有 有效 value 并且实例将处于有效状态。
当您依赖来自数据库的值作为实体值时,这种情况尤其常见。例如。自动生成的 ID,或创建和/或更新的值;这通常是数据库关注的问题。
对于自动生成的 ID,the recommended way forward是将类型声明更改为:
private ?int $id = null
对于所有其余的,只需为属性的类型选择一个合适的值。

关于php - 为什么我在引入属性类型提示时突然收到 "Typed property must not be accessed before initialization"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59265625/

相关文章:

php - 传递给 Y 的参数 X 必须是 bool 值的实例, bool 值给定 - PHP7

php - 功能 mcrypt_get_iv_size() 在 Laravel 5.5 和 php 7.1.11 上被弃用

php - 自动递增问题 - 递增 10

java - php乘法奇怪的整数溢出行为

symfony - Symfony 3 实体的自定义 JSON 序列化程序

php - 删除 Symfony 中父类的映射学说字段 [FOSUserBundle]

php - 使用 nginx 在 ubuntu 16、php 7 中显示 php 文件的白屏

php - mysql搜索数据时如何显示空值错误信息

javascript - 将动态创建的 HTML 复选框提交到数据库(MySQL)

php - Symfony2 : Entity created but, 给的类不存在