Awesome-claude-code create-unit-of-work
Generates Unit of Work pattern components for PHP 8.4. Creates transactional consistency infrastructure with aggregate tracking, flush/rollback, domain event collection, and unit tests.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-unit-of-work" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-unit-of-work && rm -rf "$T"
manifest:
skills/create-unit-of-work/SKILL.mdsource content
Unit of Work Generator
Creates Unit of Work pattern infrastructure for transactional consistency across multiple aggregates.
When to Use
| Scenario | Example |
|---|---|
| Multi-aggregate transactions | Order + Payment + Inventory in single transaction |
| Batch persistence | Flush multiple entity changes at once |
| Change tracking | Detect dirty entities for selective updates |
| Domain event collection | Collect and dispatch events after successful commit |
| Repository coordination | Ensure all repositories share the same transaction |
Component Characteristics
UnitOfWorkInterface
- Application layer port
- begin(), commit(), rollback() transaction methods
- registerNew(), registerDirty(), registerDeleted() tracking methods
- flush() to persist all tracked changes
- collectEvents() from tracked aggregates
UnitOfWork
- Infrastructure implementation (PDO/Doctrine-based)
- Identity Map for tracked entities
- Dirty checking for change detection
- Ordered persistence (inserts → updates → deletes)
- Wraps all operations in database transaction
AggregateTracker
- Tracks entity state (NEW, CLEAN, DIRTY, DELETED)
- Identity Map prevents duplicate loading
- Computes changeset on flush
TransactionManagerInterface
- Abstracts transaction lifecycle
- Supports nested transactions (savepoints)
- Domain layer contract
DomainEventCollector
- Collects events from all tracked aggregates
- Dispatches events AFTER successful commit
- Clears events on rollback
Generation Process
Step 1: Analyze Request
Determine:
- Context name (Order, Payment, Inventory)
- Which aggregates participate in unit of work
- Event dispatcher integration (Symfony/custom)
Step 2: Generate Core Components
Create in this order:
-
Domain Layer (
)src/Domain/Shared/UnitOfWork/
— State enum (New, Clean, Dirty, Deleted)EntityState.php
— Transaction contractTransactionManagerInterface.php
— Event collection contractDomainEventCollectorInterface.php
-
Application Layer (
)src/Application/Shared/UnitOfWork/
— Main portUnitOfWorkInterface.php
— Identity map and change trackingAggregateTracker.php
-
Infrastructure Layer (
)src/Infrastructure/Persistence/UnitOfWork/
— Doctrine-based implementationDoctrineUnitOfWork.php
— Doctrine transaction managerDoctrineTransactionManager.php
— Event collector with dispatcherDomainEventCollector.php
-
Tests
EntityStateTest.phpAggregateTrackerTest.phpDoctrineUnitOfWorkTest.php
Step 3: Generate Context-Specific Integration
For each context (e.g., Order):
src/Application/{Context}/ └── {Context}UnitOfWorkAware.php (trait or base class)
File Placement
| Layer | Path |
|---|---|
| Domain Types | |
| Application Port | |
| Infrastructure | |
| Unit Tests | |
Key Principles
Transaction Boundaries
- Begin transaction at use case entry
- Track all aggregate changes within boundary
- Flush all changes atomically
- Dispatch domain events after successful commit
- Rollback clears all tracked changes
Identity Map
- One entity instance per identity in memory
- Prevent duplicate loads from database
- Track original state for dirty checking
Event Ordering
- Persist all changes first
- Commit transaction
- Dispatch collected domain events
- If dispatch fails, changes are already committed (eventual consistency)
Naming Conventions
| Component | Pattern | Example |
|---|---|---|
| State Enum | | |
| Main Interface | | |
| Implementation | | |
| Tracker | | |
| Transaction | | |
| Test | | |
Quick Template Reference
UnitOfWorkInterface
interface UnitOfWorkInterface { public function begin(): void; public function commit(): void; public function rollback(): void; public function registerNew(object $entity): void; public function registerDirty(object $entity): void; public function registerDeleted(object $entity): void; public function flush(): void; }
EntityState
enum EntityState: string { case New = 'new'; case Clean = 'clean'; case Dirty = 'dirty'; case Deleted = 'deleted'; public function canTransitionTo(self $next): bool; }
Usage Pattern
$unitOfWork->begin(); try { $order = $orderRepository->findById($orderId); $order->confirm(); $unitOfWork->registerDirty($order); $payment = Payment::create($order->totalAmount()); $unitOfWork->registerNew($payment); $unitOfWork->flush(); $unitOfWork->commit(); } catch (\Throwable $e) { $unitOfWork->rollback(); throw $e; }
DI Configuration
# Symfony services.yaml Application\Shared\UnitOfWork\UnitOfWorkInterface: alias: Infrastructure\Persistence\UnitOfWork\DoctrineUnitOfWork Domain\Shared\UnitOfWork\TransactionManagerInterface: alias: Infrastructure\Persistence\UnitOfWork\DoctrineTransactionManager
Database Notes
No dedicated table needed — Unit of Work operates on existing aggregate tables. Requires database that supports transactions (PostgreSQL, MySQL with InnoDB).
References
For complete PHP templates and test examples, see:
— All component templatesreferences/templates.md
— Order + Payment transaction example and unit testsreferences/examples.md