acc-create-read-model
1
总安装量
1
周安装量
#46429
全站排名
安装命令
npx skills add https://github.com/dykyi-roman/awesome-claude-code --skill acc-create-read-model
Agent 安装分布
opencode
1
claude-code
1
Skill 文档
Read Model / Projection Generator
Creates Read Model infrastructure for CQRS read side with optimized query models.
When to Use
| Scenario | Example |
|---|---|
| CQRS read side | Separate query models |
| Denormalized views | Dashboard aggregates |
| Complex queries | Multi-entity joins |
| Event-driven updates | Event projections |
Component Characteristics
Read Model
- Optimized for queries
- Denormalized data
- Eventually consistent
- No business logic
Projection
- Builds read models from events
- Handles event streams
- Maintains synchronization
- Idempotent processing
Repository
- Query-focused methods
- Returns read models
- No write operations
Generation Process
Step 1: Generate Domain Read Model
Path: src/Domain/{BoundedContext}/ReadModel/
{Name}ReadModel.phpâ Immutable read model with fromArray/toArray{Name}ReadModelRepositoryInterface.phpâ Query-focused repository interface
Step 2: Generate Application Projection
Path: src/Application/{BoundedContext}/Projection/
{Name}ProjectionInterface.phpâ Projection contract{Name}Projection.phpâ Event handlers building read model
Step 3: Generate Infrastructure
Path: src/Infrastructure/{BoundedContext}/
Projection/{Name}Store.phpâ Store for insert/update/upsertReadModel/Doctrine{Name}Repository.phpâ Repository implementation
Step 4: Generate Tests
{Name}ReadModelTest.phpâ Read model serialization tests{Name}ProjectionTest.phpâ Projection event handling tests
File Placement
| Component | Path |
|---|---|
| Read Model | src/Domain/{BoundedContext}/ReadModel/ |
| Repository Interface | src/Domain/{BoundedContext}/ReadModel/ |
| Projection Interface | src/Application/{BoundedContext}/Projection/ |
| Projection | src/Application/{BoundedContext}/Projection/ |
| Store | src/Infrastructure/{BoundedContext}/Projection/ |
| Repository Impl | src/Infrastructure/{BoundedContext}/ReadModel/ |
| Unit Tests | tests/Unit/ |
Naming Conventions
| Component | Pattern | Example |
|---|---|---|
| Read Model | {Name}ReadModel |
OrderSummaryReadModel |
| Repository Interface | {Name}ReadModelRepositoryInterface |
OrderSummaryReadModelRepositoryInterface |
| Projection Interface | {Name}ProjectionInterface |
OrderSummaryProjectionInterface |
| Projection | {Name}Projection |
OrderSummaryProjection |
| Store | {Name}Store |
OrderSummaryStore |
| Test | {ClassName}Test |
OrderSummaryProjectionTest |
Quick Template Reference
Read Model
final readonly class {Name}ReadModel
{
public function __construct(
public string $id,
// ... denormalized properties
public \DateTimeImmutable $createdAt,
public \DateTimeImmutable $updatedAt
) {}
public static function fromArray(array $data): self;
public function toArray(): array;
}
Projection
final class {Name}Projection implements {Name}ProjectionInterface
{
public function project(DomainEventInterface $event): void
{
match ($event::class) {
OrderCreated::class => $this->whenOrderCreated($event),
OrderShipped::class => $this->whenOrderShipped($event),
default => null,
};
}
public function reset(): void;
public function subscribedEvents(): array;
}
Usage Example
// Query read model
$orders = $orderSummaryRepository->findByCustomerId($customerId);
// Project event
$projection->project($orderCreatedEvent);
// Reset projection for rebuild
$projection->reset();
Database Schema
CREATE TABLE order_summaries (
id VARCHAR(36) PRIMARY KEY,
order_number VARCHAR(50) NOT NULL UNIQUE,
customer_id VARCHAR(36) NOT NULL,
customer_name VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL,
total_cents BIGINT NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL,
INDEX idx_customer (customer_id),
INDEX idx_status (status)
);
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Business Logic | Read model has behavior | Keep data-only |
| Write Operations | Modifying read models | Use projections only |
| Non-idempotent | Re-projection breaks data | Idempotent event handling |
| Missing Reset | Can’t rebuild | Add reset() method |
| Tight Coupling | Projection depends on domain | Use events only |
References
For complete PHP templates and examples, see:
references/templates.mdâ Read model, projection, store templatesreferences/examples.mdâ OrderSummary example and tests