phpphpstan

PHP 7.4+ class property typing


I'm sure that question has been asked numerous times but I can't seem to find a good/satisfying answer so please bare with me.

Using PHP 7.4+, I tend to type everything I can. But I have some problems with Doctrine entities properties.

If I type everything correctly, I usually get a lot of errors like this one.

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

A code sample for that type of error would look something like this

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

So, I used to make the property nullable even though the database field is not. So it would look something like this.

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

But, now I have another problem. I decided to implement a static code analyzer in my project and now I'm using PHPStan. So now, when I scan my code I get errors like that one.


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.


Sometimes, I don't want to/can't initialize the property in the constructor since I don't have the correct values just yet.

What would be the right way to handle this type of situation?


Solution

  • I'm not sure if this is a bad practice, but it turned out I only had to remove that check from phpstan configuration.

    # phpstan.neon
    parameters:
      doctrine:
        allowNullablePropertyForRequiredField: true
    

    After some digging, I realized I should be using a DTO which would allow a null value, and then transfer it to my entity once ready (and valid). This way, my entity is always valid, and I do not risk flushing some invalid data in the DB.