Installation:
composer require biig/domain
For Laravel (Symfony-compatible), ensure you have symfony/doctrine-bridge and doctrine/orm installed.
First Use Case: Define a Domain Event and dispatch it from a Doctrine entity:
// src/Domain/Events/UserRegistered.php
namespace App\Domain\Events;
use Biig\Domain\DomainEvent;
class UserRegistered extends DomainEvent
{
public function __construct(private int $userId) {}
public function getUserId(): int { return $this->userId; }
}
Dispatch it in an entity:
// src/Domain/Entities/User.php
namespace App\Domain\Entities;
use Biig\Domain\DomainEventDispatcher;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class User
{
#[ORM\Id, ORM\GeneratedValue]
private ?int $id = null;
public function register(DomainEventDispatcher $dispatcher): void
{
$this->id = 123; // Simulate ID assignment
$dispatcher->dispatch(new UserRegistered($this->id));
}
}
Register the Dispatcher:
In config/services.php (Laravel) or Symfony DI container:
// Laravel: config/services.php
'domain_event_dispatcher' => Biig\Domain\DomainEventDispatcher::class,
Event-Driven Domain Logic:
OrderShipped event after saving an Order entity.Factory Pattern for Entities:
// src/Domain/Factories/UserFactory.php
class UserFactory
{
public function create(array $data): User
{
$user = new User();
$user->setName($data['name']);
return $user;
}
}
Symfony Serializer Integration:
use Biig\Domain\Serializer\DomainEventSerializer;
$serializer = new DomainEventSerializer();
$eventJson = $serializer->serialize([new UserRegistered(1)], 'json');
Doctrine Event Listeners:
config/packages/doctrine.yaml (Symfony) or Laravel's EventServiceProvider:
# Symfony
doctrine:
orm:
event_listeners:
App\Domain\Listeners\SendWelcomeEmail:
tags: [doctrine.event_listener]
Laravel-Specific:
AppServiceProvider:
public function register()
{
$this->app->singleton(DomainEventDispatcher::class, function ($app) {
return new DomainEventDispatcher();
});
}
Event facade to listen to domain events (if needed):
use Illuminate\Support\Facades\Event;
Event::listen(UserRegistered::class, function ($event) {
// Handle event
});
ApiPlatform:
@ApiResource to expose them as API endpoints:
use ApiPlatform\Core\Annotation\ApiResource;
#[ApiResource]
class UserRegistered extends DomainEvent {}
Entity Instantiation:
new User()) will fail if they rely on the dispatcher.Circular Dependencies:
register(DomainEventDispatcher $dispatcher)).Event Dispatch Timing:
prePersist/preUpdate Doctrine lifecycle callbacks or after explicit persistence.Serializer Compatibility:
JsonSerializable or add Symfony serializer groups:
use Symfony\Component\Serializer\Annotation\Groups;
class UserRegistered extends DomainEvent
{
#[Groups(['event'])]
public function getUserId(): int { return $this->userId; }
}
Event Dispatch Logs:
Enable debug logs for the biig.domain channel in config/logging.php (Laravel) or Symfony's monolog config:
'channels' => [
'biig.domain' => [
'driver' => 'single',
'path' => storage_path('logs/domain.log'),
'level' => 'debug',
],
],
Doctrine Event Debugging:
Use stderr logging for Doctrine events:
# config/packages/doctrine.yaml (Symfony)
doctrine:
orm:
logging: true
logging_params:
log_to_stderr: true
Custom Event Dispatcher:
DomainEventDispatcher to add middleware or logging:
class CustomDispatcher extends DomainEventDispatcher
{
public function dispatch(DomainEvent $event): void
{
logger()->debug("Dispatching event: " . get_class($event));
parent::dispatch($event);
}
}
Event Subscribers:
use Biig\Domain\DomainEventSubscriber;
class AuditSubscriber implements DomainEventSubscriber
{
public function getSubscribedEvents(): array
{
return [
UserRegistered::class => 'onUserRegistered',
];
}
public function onUserRegistered(UserRegistered $event): void
{
// Audit logic
}
}
Doctrine Extensions:
#[ORM\Entity]
class User
{
#[ORM\LifecycleCallbacks]
class UserCallbacks
{
public function prePersist(User $user, EntityManagerInterface $em)
{
$user->dispatcher->dispatch(new UserRegistered($user->id));
}
}
}
$dispatcher->dispatch(new BulkUserRegistered([1, 2, 3]));
UnitOfWork to defer event dispatching until flush:
$em->persist($user);
$em->flush(); // Events dispatch here
How can I help you explore Laravel packages today?