Skip to main content

Tips

This chapter explains the tips and our best practices that others might find useful, but not strictly required.

Use UUIDs as Identifiers

Use UUIDs as entity identifiers & have the entities generate one for themselves on instantiation. That means new entities already have an ID before flush().

use Symfony\Component\Uid\UuidV7;

class Post
{
private string $id;

public function __construct(string $title)
{
$this->id = new UuidV7();
}

// ...
}

This way, you can reliably store the ID in your event objects, instead of the object itself. Using the ID in the events means your events can be reliably serialized. It improves logistics because you can pass them anywhere without modification, and without creating additional event objects.

Persist Early after Entity Creation

On entity creation, persist() your entities early, and flush() late. This is especially important if you are using the immediate listening strategy. It will let your listener obtain the entity instance by calling find() on the repository using the entity's identifier.

$post = new Post();
$entityManager->persist($post);

$post->setContent('Hello, World!');

$entityManager->flush();

Choosing Dispatching Strategy

If you want to do something similar to what you are used to doing with application events, you probably want the post-flush strategy. If you are already using Symfony Messenger, consider using the event bus strategy instead for more reliability.

Use pre-flush events to make alterations to your domain that will be flush()-ed together along with the other changes.

No Event Inheritance, Yet

Symfony Event Dispatcher does not currently support event inheritance. This needs to be mentioned because many programmers expect an event dispatcher to support event inheritance, especially when working with a large amount of event objects.

This is not ideal, and we want this feature in the future. But for now, this is a limitation that you need to be aware of.

Idempotent Event Bus Listeners

Idempotence is a desirable trait in event bus messaging. This means if a listener receives the same event multiple times, it should have the same effect as if it received the event only once.

With an event bus, a system failure might cause the same event to be dispatched more than once. An idempotent listener won't cause any harm when that happens.

In simpler cases, you can leverage EquatableDomainEventInterface. If your event implements EquatableDomainEventInterface, your listener can get the event's signature and store it somewhere. If the event is dispatched again, the listener can check if it has already processed the event.