Help us improve
Share bugs, ideas, or general feedback.
How this skill is triggered — by the user, by Claude, or both
Slash command
/acc:create-repositoryThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate DDD-compliant Repository interfaces and implementation stubs.
Generates DDD-compliant aggregates for PHP 8.4 with root entity, child entities, domain events, invariant protection, and unit tests.
Generates Repository interfaces and EF Core implementations per aggregate root, with query methods and Unit of Work integration for .NET DDD projects.
Implements Clean Architecture, Hexagonal (Ports & Adapters), and Domain-Driven Design patterns in PHP 8.3+ with Symfony 7.x. For enterprise app architecture, legacy refactoring, DDD, and testable backends.
Share bugs, ideas, or general feedback.
Generate DDD-compliant Repository interfaces and implementation stubs.
Path: src/Domain/{BoundedContext}/Repository/
{AggregateRoot}RepositoryInterface.php — Domain contractPath: src/Infrastructure/Persistence/Doctrine/
Doctrine{AggregateRoot}Repository.php — Doctrine implementationPath: tests/Infrastructure/Persistence/
InMemory{AggregateRoot}Repository.php — For unit testingPath: tests/Integration/Infrastructure/Persistence/
| Component | Path |
|---|---|
| Interface | src/Domain/{BoundedContext}/Repository/ |
| Doctrine Impl | src/Infrastructure/Persistence/Doctrine/ |
| In-Memory | tests/Infrastructure/Persistence/ |
| Integration Tests | tests/Integration/Infrastructure/Persistence/ |
| Component | Pattern | Example |
|---|---|---|
| Interface | {AggregateRoot}RepositoryInterface | OrderRepositoryInterface |
| Doctrine Impl | Doctrine{AggregateRoot}Repository | DoctrineOrderRepository |
| In-Memory | InMemory{AggregateRoot}Repository | InMemoryOrderRepository |
interface {AggregateRoot}RepositoryInterface
{
public function findById({AggregateRoot}Id $id): ?{AggregateRoot};
public function save({AggregateRoot} $aggregate): void;
public function remove({AggregateRoot} $aggregate): void;
public function nextIdentity(): {AggregateRoot}Id;
}
final readonly class Doctrine{AggregateRoot}Repository implements {AggregateRoot}RepositoryInterface
{
public function __construct(
private EntityManagerInterface $em
) {}
public function findById({AggregateRoot}Id $id): ?{AggregateRoot}
{
return $this->em->find({AggregateRoot}::class, $id->value);
}
public function save({AggregateRoot} $aggregate): void
{
$this->em->persist($aggregate);
$this->em->flush();
}
public function remove({AggregateRoot} $aggregate): void
{
$this->em->remove($aggregate);
$this->em->flush();
}
public function nextIdentity(): {AggregateRoot}Id
{
return {AggregateRoot}Id::generate();
}
}
final class InMemory{AggregateRoot}Repository implements {AggregateRoot}RepositoryInterface
{
private array $items = [];
public function findById({AggregateRoot}Id $id): ?{AggregateRoot}
{
return $this->items[$id->value] ?? null;
}
public function save({AggregateRoot} $aggregate): void
{
$this->items[$aggregate->id()->value] = $aggregate;
}
public function clear(): void
{
$this->items = [];
}
}
| Rule | Good | Bad |
|---|---|---|
| Layer Placement | Interface in Domain | Interface in Infrastructure |
| Aggregate Scope | Repository per aggregate root | Repository per entity |
| Query Methods | Simple filters | Business logic in queries |
| Identity | nextIdentity() method | External ID generation |
| Anti-pattern | Problem | Solution |
|---|---|---|
| Entity Repository | Bypasses aggregate | Only aggregate roots |
| Business Queries | Logic in repository | Use Specification pattern |
| Infrastructure Leak | Domain depends on ORM | Interface in Domain |
| Generic Repository | Too abstract | Specific per aggregate |
| Missing nextIdentity | Can't generate IDs | Add to interface |
For complete PHP templates and examples, see:
references/templates.md — Interface, Doctrine, In-Memory, Test templatesreferences/examples.md — Order, User repositories with Doctrine and In-Memory implementations