This is a proof of concept for a mapping fields with Doctrine ORM so they can be serialized with the Symfony Serializer component, without the need to create a mapping type for each possible data type.
Sometimes you just need to store a complex data type (generally a Value Object) in a JSON field and not worry about database schemas, extra columns or tables, Doctrine embeddables, custom mappings.
This library requires PHP 8.0 or later.
composer require edudobay/doctrine-symfony-serializer
See the examples directory for a working code example.
Add this to your application setup:
use Edudobay\DoctrineSerializable\ReflectionClassMetadataFactory;
use Edudobay\DoctrineSerializable\SerializationHandler;
use Edudobay\DoctrineSerializable\PersistenceEventSubscriber;
$serializer = ...; // Symfony Serializer
$entityManager = ...; // Doctrine ORM EntityManager
$subscriber = new PersistenceEventSubscriber(new SerializationHandler(
$serializer,
// You might want to cache this. See Psr6CacheClassMetadataFactory
new ReflectionClassMetadataFactory()
));
$entityManager->getEventManager()->addEventSubscriber($subscriber);
In your entities, have your domain object as you like, and introduce a private backing field that will make it persistent:
use Doctrine\ORM\Mapping as ORM;
use Edudobay\DoctrineSerializable\Attributes\Serializable;
#[ORM\Entity]
class User
{
// Backing field
#[ORM\Column('address', type: 'json')]
private array $_address = [];
// The actual domain object
#[Serializable]
public Address $address;
// For arrays:
#[ORM\Column('badges', type: 'json')]
private array $_badges = [];
#[Serializable]
/** @var Badge[] */
public array $badges;
// OPTIONAL: use arrayItemType instead of docblock array types
#[Serializable(arrayItemType: Badge::class)]
public array $badges;
}