PHP 7.4+ class 属性 打字

PHP 7.4+ class property typing

我确定这个问题已经被问过很多次了,但我似乎找不到 good/satisfying 答案,所以请耐心等待。

使用 PHP 7.4+,我倾向于输入我能输入的所有内容。但是我对 Doctrine 实体属性有一些问题。

如果我输入的所有内容都正确,我通常会遇到很多这样的错误。

Typed property App\Entity\User::$createdAt must not be accessed before initialization

该类型错误的代码示例如下所示

/**
 * @var DateTimeInterface
 * @ORM\Column(type="datetime")
 */
protected DateTimeInterface $createdAt;

所以,我曾经使 属性 可以为 null,即使数据库字段不是。所以它看起来像这样。

/**
 * @var DateTimeInterface|null
 * @ORM\Column(type="datetime")
 */
protected ?DateTimeInterface $createdAt = null;

但是,现在我有另一个问题。我决定在我的项目中实现一个静态代码分析器,现在我正在使用 PHPStan。所以现在,当我扫描我的代码时,我会收到类似的错误。


Line src/Entity/Trait/TimestampableEntityPropertiesTrait.php (in context of class App\Entity\Article)


16 Property App\Entity\Article::$createdAt type mapping mismatch: property can contain DateTimeInterface|null but database expects DateTimeInterface.


那么,处理这种情况的正确方法是什么?

如有任何建议,我们将不胜感激。

编辑

我应该提到,有时我不想 to/can 不在构造函数中初始化 属性,因为我还没有正确的值。

我不确定这是否是一个坏习惯,但事实证明我只需要从 phpstan 配置中删除该检查。

# phpstan.neon
parameters:
  doctrine:
    allowNullablePropertyForRequiredField: true

编辑:

经过一些挖掘,我意识到我应该使用允许空值的 DTO,然后在准备好(且有效)后将其传输到我的实体。这样,我的实体总是有效的,我不会冒险刷新数据库中的一些无效数据。

phpstan 代码味道可能并没有那么错...
实际的 Doctrine 注释是 nullable=true:

/**
 * @ORM\Column(type="datetime", nullable=true)
 */

然后 ORM 将停止抱怨意外的 NULL 值。
没有它,created_at 将设置 NOT NULL;因此它是“必需的”。

关键是,当它是 nullable=true 时,就不再需要它了。
而当它不再需要时,phpstan也会停止抱怨

而另一方面,当让 phpstan 忽略与 allowNullablePropertyForRequiredField: true 在应用程序级别上的这些冲突时,这对基础数据库的影响为零,基础数据库将拒绝记录,基于用于生成数据库的注释 table.