Api Platform Dto Resources (Symfony)
Use when
- The
#[ApiResource] class must be the API contract, decoupled from the Doctrine entity.
- Entity and API fields differ in name or format (rename, formatted price, computed value).
- Create, update, or list operations need their own input or output shape.
- Migrating code that relied on
DataTransformerInterface, which no longer exists.
Default workflow
- Require
symfony/object-mapper and set stateOptions: new Options(entityClass: ...) on the DTO resource.
- Bind the DTO and the entity with
#[Map(source: ...)] and #[Map(target: ...)], and use #[Map(transform: ...)] for computed fields.
- For distinct shapes, create input and output classes and wire them with
input: and output: on each operation.
- When mapping needs real logic, write a custom
ProcessorInterface that calls ObjectMapperInterface::map().
- Test each operation: payload in, response shape out.
Guardrails
- The automatic Object Mapper provider and processor only apply when
stateOptions has an entityClass and both the DTO and the entity carry #[Map].
DataTransformerInterface is gone: use Object Mapper or a provider and processor.
- No Object Mapper on 3.4 or on Symfony 6.4 LTS (it needs Symfony 7.3+): map manually in a
ProviderInterface and a ProcessorInterface.
ObjectMapperProcessor is removed in 5.0: the automatic path uses ObjectMapperInputProcessor and ObjectMapperOutputProcessor (4.3+).
- Never return the entity itself from a DTO resource: only mapped fields reach the client.
Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
Output contract
- The resource, input, and output classes with their
#[Map] bindings.
- The mapping path chosen (Object Mapper or custom processor) and why.
- Tests showing the request and response shape of each operation.
References