Null or Nullable Embeddables with Symfony and Doctrine ORM
(Updated for PHP 8 using attributes)
I wrote an article about nullable Embeddables in 2020 here. Go there for the background story and motivation for the following code. The mentioned problem is still not solved and there are various issues on GitHub.
This article is about an updated solution using PHP 8 attributes (probably faster).
Interfaces
In this solution we do without interfaces, so we remove them.
Attributes
I use one class level attribute #[ContainsNullableEmbeddable]
to identify an entity that contains Embeddables that can be null
:
use Attribute;#[Attribute(Attribute::TARGET_CLASS)]
final class ContainsNullableEmbeddable
{
}
and a property level attribute #[Nullable]
I set on every property that’s a nullable Embeddable:
use Attribute;#[Attribute(Attribute::TARGET_PROPERTY)]
final class Nullable
{
}
Now the entity class looks like this:
use App\Attribute\ContainsNullableEmbeddable;
use App\Attribute\Nullable;
use Doctrine\ORM\Mapping\Embedded;
use Doctrine\ORM\Mapping\Entity;#[Entity]
#[ContainsNullableEmbeddable]
final class Contact
{
#[Embedded(class: EmailAddress::class, columnPrefix: false)]
#[Nullable]
private ?EmailAddress $emailAddress;
…
}
That’s all that’s required in our entity class.
Doctrine Event Subscriber
I changed the code for the Doctrine event subscriber as follows:
The ReflectionClass::getAttributes
method takes an attribute class name as first argument and returns only matching attributes.
I also added a check for uninitialized typed properties and count them as null
.
Happy coding!