# Symfony Domain Modeling

> Symfony domain modeling — entities, value objects, domain events, aggregates, domain exceptions. Triggers on: entity, value object, domain event, aggregate, domain exception, domain model, domain logic, business rule, invariant

- Skill: `aligundogdu/symfony-domain-modeling` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add aligundogdu/symfony-domain-modeling`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aligundogdu/symfony-domain-modeling/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: aligundogdu (https://skillmd.com/u/aligundogdu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aligundogdu/symfony-domain-modeling

---


# Symfony Domain Modeling

You are an expert in Domain-Driven Design within Symfony hexagonal architecture. Use this skill when users need to create or modify domain model elements.

## When to Activate

- User wants to create an entity or aggregate root
- User asks about value objects
- User needs domain events
- User mentions domain exceptions or business rules
- User discusses aggregates or invariants

## Entity Patterns

### Rules
- Private constructor + static factory method(s)
- No Doctrine annotations/attributes — mapping is in Infrastructure
- Record domain events on state changes
- Protect invariants in methods, not in external validators
- Use value objects for typed properties (no primitive obsession)

### Template
```php
namespace App\Domain\{Module}\Entity;

final class {Entity}
{
    private array $domainEvents = [];

    private function __construct(
        private {EntityId} $id,
        // typed properties using value objects
    ) {
    }

    public static function create(/* params */): self
    {
        // validate invariants
        $entity = new self(/* params */);
        $entity->recordEvent(new {Entity}Created(/* event data */));
        return $entity;
    }

    // Business methods that protect invariants
    public function doAction(/* params */): void
    {
        // guard clause / invariant check
        // state change
        $this->recordEvent(new {ActionDone}(/* event data */));
    }

    public function pullDomainEvents(): array
    {
        $events = $this->domainEvents;
        $this->domainEvents = [];
        return $events;
    }

    private function recordEvent(object $event): void
    {
        $this->domainEvents[] = $event;
    }
}
```

## Value Object Patterns

### Rules
- Always `final readonly class`
- Self-validating in constructor (throw domain exception if invalid)
- Immutable — no setters
- Implement `equals()` for comparison
- Use for: IDs, email, money, dates, status enums

### Template
```php
namespace App\Domain\{Module}\ValueObject;

use App\Domain\{Module}\Exception\Invalid{ValueObject}Exception;

final readonly class {ValueObject}
{
    public function __construct(
        public string $value,
    ) {
        if (/* validation fails */) {
            throw new Invalid{ValueObject}Exception($value);
        }
    }

    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}
```

## Domain Event Patterns

### Rules
- Past-tense naming: `UserRegistered`, `OrderPlaced`, `PaymentFailed`
- Immutable (`final readonly class`)
- Carry only the data needed by handlers (IDs, not full entities)
- Created inside entities on state changes

### Template
```php
namespace App\Domain\{Module}\Event;

final readonly class {PastTenseEvent}
{
    public function __construct(
        public string $entityId,
        public \DateTimeImmutable $occurredAt = new \DateTimeImmutable(),
        // additional event-specific data
    ) {
    }
}
```

## Domain Exception Patterns

```php
namespace App\Domain\{Module}\Exception;

final class {DomainException} extends \DomainException
{
    public static function because{Reason}(/* context */): self
    {
        return new self(sprintf('Descriptive message: %s', $context));
    }
}
```

## References

See `references/` for detailed patterns:
- `entity-patterns.md` — Full entity examples with aggregates
- `value-object-patterns.md` — Common value object implementations
- `domain-event-patterns.md` — Event design and dispatch patterns

