From acc
Traces data transformations from Request DTO through Commands, Entities to Response DTOs in PHP apps. Identifies mappers, serializers, converters, type conversions, and data loss points across layers.
How this skill is triggered — by the user, by Claude, or both
Slash command
/acc:trace-data-transformationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Traces how data transforms as it passes through application layers — from raw HTTP input through DTOs, Commands, Entities, and back to Response objects. Identifies mappers, serializers, converters, and potential data loss points.
Traces how data transforms as it passes through application layers — from raw HTTP input through DTOs, Commands, Entities, and back to Response objects. Identifies mappers, serializers, converters, and potential data loss points.
HTTP Request Body (JSON/Form)
→ Request DTO (validated input)
→ Command/Query (application layer input)
→ Entity/Aggregate (domain model)
→ Domain Event (side effect data)
→ Response DTO (output format)
→ HTTP Response (JSON/XML)
# Request DTOs / Form Requests
Grep: "class.*Request|class.*Input" --glob "**/Api/**/*.php"
Grep: "class.*Request" --glob "**/Presentation/**/*.php"
# Request to Command mapping
Grep: "new.*Command\\(|Command::from|Command::create" --glob "**/*.php"
# Deserialization
Grep: "deserialize|fromArray|fromRequest|fromJson" --glob "**/*.php"
Grep: "Serializer::deserialize|denormalize" --glob "**/*.php"
# Entity factories / named constructors
Grep: "static function (create|from|of|new)" --glob "**/Domain/**/*.php"
# Entity to DTO conversion
Grep: "function (toArray|toDTO|toResponse|toView)" --glob "**/Domain/**/*.php"
Grep: "::fromEntity|::fromDomain|::fromModel" --glob "**/*.php"
# Response DTOs
Grep: "class.*Response|class.*Output|class.*View" --glob "**/Api/**/*.php"
Grep: "class.*Resource" --glob "**/Http/**/*.php"
# Serialization
Grep: "jsonSerialize|toArray|normalize" --glob "**/*.php"
Grep: "JsonResponse|json_encode" --glob "**/*.php"
# Collection transformation
Grep: "->map\\(|array_map|->transform" --glob "**/*.php"
# Explicit mapper classes
Grep: "class.*Mapper|class.*Converter|class.*Transformer|class.*Assembler" --glob "**/*.php"
# Mapping methods
Grep: "function (map|convert|transform|assemble|adapt)" --glob "**/*.php"
# AutoMapper / Symfony Serializer
Grep: "AutoMapper|ObjectNormalizer|PropertyNormalizer" --glob "**/*.php"
For a given request flow:
| Source | Target | Transformation |
|---|---|---|
request.customer_name | CreateOrderCommand.customerName | snake_case → camelCase |
command.customerId | Customer entity | ID → full entity (repo lookup) |
entity.createdAt | response.created_at | DateTime → string ISO 8601 |
entity.money | response.amount | Money VO → float |
Check for:
## Data Transformation Map
### Flow: Create Order
#### Transformation Chain
[1] JSON Input { "customer_id": "uuid-123", "items": [{"product_id": "p-1", "quantity": 2}], "shipping_address": {"street": "...", "city": "..."} } │ ▼ (Deserialization + Validation) [2] CreateOrderRequest customerId: string (validated: uuid format) items: CreateOrderItemRequest[] (validated: non-empty) shippingAddress: AddressRequest (validated: all fields required) │ ▼ (Mapping: CreateOrderRequest → CreateOrderCommand) [3] CreateOrderCommand customerId: CustomerId (Value Object wrapping) items: OrderItemData[] (DTO with productId + quantity) shippingAddress: AddressData (DTO) │ ▼ (Domain Factory: Order::create()) [4] Order Entity id: OrderId (generated) customerId: CustomerId items: OrderItem[] (entities with calculated prices) total: Money (calculated from items) status: OrderStatus::Pending shippingAddress: ShippingAddress (Value Object) createdAt: DateTimeImmutable │ ▼ (Response Mapping: OrderResponse::fromEntity()) [5] OrderResponse id: string (OrderId → string) customerId: string (CustomerId → string) items: OrderItemResponse[] (entity → response) total: float (Money → float, currency separate) currency: string (from Money) status: string (enum → string) shippingAddress: AddressResponse createdAt: string (ISO 8601) │ ▼ (JSON Serialization) [6] JSON Output {"id": "...", "customer_id": "...", "total": 150.00, ...}
#### Field Mapping Table
| Layer | Field | Type | Source | Transformation |
|-------|-------|------|--------|---------------|
| Input → Request | customer_id → customerId | string | JSON key | snake → camel |
| Request → Command | customerId → customerId | string → CustomerId | DTO | Wrap in VO |
| Command → Entity | items → OrderItem[] | DTO[] → Entity[] | Factory | Enrich with prices |
| Entity → Response | total → total | Money → float | Mapper | Extract amount |
| Entity → Response | createdAt → createdAt | DateTimeImmutable → string | Mapper | Format ISO 8601 |
| Response → JSON | customerId → customer_id | string | Serializer | camel → snake |
#### Data Enrichment Points
| Step | What's Added | Source |
|------|-------------|--------|
| Command → Entity | OrderId | Generated (UUID) |
| Command → Entity | Item prices | ProductRepository lookup |
| Command → Entity | Total amount | Calculated from items |
| Command → Entity | Created timestamp | System clock |
| Command → Entity | Initial status | Domain default (Pending) |
#### Potential Data Loss Points
| Step | Field | Issue |
|------|-------|-------|
| Money → float | precision | Floating point precision loss |
| DateTime → string | timezone | Check if timezone preserved |
| Entity → Response | internal state | Domain internals not exposed (expected) |
| Indicator | Good | Warning |
|---|---|---|
| Type safety | Typed DTOs at boundaries | Untyped arrays |
| Validation | At input boundary | Scattered or missing |
| Mapping | Explicit mapper/factory | Implicit in controller |
| Value Objects | Domain uses VOs | Primitives throughout |
| Serialization | Controlled (toArray/normalize) | json_encode on entity |
| Anti-Pattern | Detection | Issue |
|---|---|---|
| Entity as Response | return json_encode($entity) | Exposes internals |
| Array transport | $data = ['key' => $value] | No type safety |
| Missing DTO | Controller → Repository direct | Skips validation |
| Leaky abstraction | Domain types in API response | Tight coupling |
This skill is used by:
data-flow-analyst — documents data transformation chainstrace-request-lifecycle — enriches lifecycle with data detailsexplain-business-process — shows data perspective of processesnpx claudepluginhub dykyi-roman/awesome-claude-code --plugin accTraces HTTP request lifecycle from router through middleware, controller, use case, repository to response in PHP apps. Documents routes, methods, stacks, codes, errors.
Traces feature, request, or data flows through codebase from entry points (API routes, UI handlers, jobs) to storage, documenting layers, transformations, side effects, and dependencies via graphs or grep.
Designs Value Objects for domain concepts and DTOs for data transfer with readonly immutability and validation in Symfony projects.