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?
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.