tito10047 / type-safe-id-bundle
Type safe UUID or Ulid bundle
Package info
github.com/tito10047/type-safe-id-bundle
Type:symfony-bundle
pkg:composer/tito10047/type-safe-id-bundle
Requires
- php: >=8.2
- league/construct-finder: ^1.5
- symfony/framework-bundle: ^7.4|^8.0
Requires (Dev)
- doctrine/doctrine-migrations-bundle: ^3.7
- symfony/maker-bundle: ^1.64
- symfony/orm-pack: ^2.7
- symfony/test-pack: ^1.2
- symfony/uid: ^7.4|^8.0
README
Introduction
⚠️ WARNING: This is an experimental package and may not be suitable for production use. Use at your own risk.
🏗️ DDD Ready
This bundle is designed with Domain-Driven Design (DDD) in mind. It allows you to separate your domain entities, their unique type-safe identifiers, and repositories into different namespaces or directories through configuration.
When working with Symfony and Doctrine, using UUIDs as entity identifiers is a common approach. Traditionally, IDs are stored as simple integers or as raw Uuid objects. However, this can lead to type confusion, especially when working with Symfony Messenger or repository methods. A more robust and type-safe approach is to use dedicated ID classes.
📊 Performance Benchmarks - See detailed performance analysis comparing TypeSafeId with classic Doctrine approach.
This package provides bin/console make:entity:type to generate entities with Type-safe identifiers. This is implementation
of this article
It generates something like this:
$ bin/console make:entity:type Foo --with-ulid
#[ORM\Entity(repositoryClass: FooRepository::class)] class Foo { #[ORM\Id] #[ORM\GeneratedValue(strategy: 'CUSTOM')] #[ORM\CustomIdGenerator(class: 'doctrine.id_generator.universal')] #[ORM\Column(type: FooIdType::class, unique: true)] private ?FooId $id = null; public function getId(): FooId { return $this->id; } }
class FooRepository extends ServiceEntityRepository { //... public function get(FooId $id): ?Foo { return $this->find($id->toString()); } //... }
Configuration (DDD Support)
You can customize where your files are generated by specifying their namespaces. This is especially useful for DDD structures.
Create a configuration file config/packages/type_safe_id.yaml:
type_safe_id: # Default values: entity_namespace: 'App\Entity' type_id_namespace: 'App\EntityId' repository_namespace: 'App\Repository'
If you use a different structure (e.g. src\Domain\User), the maker command will respect these namespaces.
Usage
// IDs are automatically generated by Doctrine when persisting entities $foo = new Foo(); $poo = new Poo(); $this->em->persist($foo); $this->em->persist($poo); $this->em->flush(); $serializedFooId = serialize($foo->getId()); $serializedPooId = serialize($poo->getId()); // This works - correct type $foo = $this->fooRepository->get(unserialize($serializedFooId)); // This throws Exception: App\Repository\FooRepository::get(): // Argument #1 ($id) must be of type App\EntityId\FooId, App\EntityId\PooId given $foo = $this->fooRepository->get(unserialize($serializedPooId));
Installation
Make sure Composer is installed globally, as explained in the installation chapter of the Composer documentation.
Applications that use Symfony Flex
Open a command console, enter your project directory and execute:
$ composer require tito10047/type-safe-id-bundle
Applications that don't use Symfony Flex
Step 1: Download the Bundle
Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:
$ composer require tito10047/type-safe-id-bundle
Step 2: Enable the Bundle
Then, enable the bundle by adding it to the list of registered bundles
in the config/bundles.php file of your project:
// config/bundles.php return [ // ... Tito10047\TypeSafeIdBundle\TypeSafeIdBundle::class => ['all' => true], ];