
Symfony:api Platform Dto Resources Skill
- 425 installs
- 190 repo stars
- Updated August 6, 2026
- makfly/superpowers-symfony
symfony:api-platform-dto-resources is a Symfony agent skill that models API Platform resources with DTO input and output objects so developers expose clean REST contracts without leaking Doctrine entities.
About
symfony:api-platform-dto-resources is a makfly/superpowers-symfony skill for PHP engineers using Symfony and API Platform who need decoupled REST contracts. It guides modeling resources with dedicated DTO classes for request input and response output instead of exposing Doctrine entities directly across API boundaries. Developers reach for this skill when designing Create, Read, Update endpoints that require validation layers, field whitelisting, or version-stable JSON shapes. The pattern prevents entity graphs, lazy-loading surprises, and internal schema drift from appearing in public APIs. Use it during backend implementation when API Platform resource classes need explicit DTO mapping.
- API Platform DTO resources
- input/output separation
- serializer mapping
- entity leak prevention
- REST contract hygiene
Symfony:Api Platform Dto Resources by the numbers
- 425 all-time installs (skills.sh)
- Ranked #21 of 68 PHP & Laravel skills by installs in the Skillselion catalog
- Data as of Aug 11, 2026 (Skillselion catalog sync)
npx skills add https://github.com/makfly/superpowers-symfony --skill symfonyapi-platform-dto-resourcesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 425 |
|---|---|
| repo stars | ★ 190 |
| Last updated | August 6, 2026 |
| Repository | makfly/superpowers-symfony ↗ |
How do you expose DTOs in API Platform Symfony?
Model API Platform resources with DTO input/output objects in Symfony when exposing clean REST contracts without leaking Doctrine entities across layers.
Who is it for?
Symfony developers exposing API Platform REST endpoints who must hide Doctrine entities behind DTO layers.
Skip if: Non-PHP stacks or Symfony apps serving entities directly without API Platform or DTO separation needs.
When should I use this skill?
Implementing API Platform endpoints that need DTO input/output instead of Doctrine entity serialization.
What you get
API Platform resource definitions with DTO input/output classes and decoupled REST JSON contracts.
Files
Api Platform Dto Resources (Symfony)
Use when
- Designing or evolving API Platform contracts and operations.
- Aligning serialization, validation, and security behavior.
Default workflow
1. Define operation-level contract and payload boundaries. 2. Implement resource/DTO/provider/processor changes with explicit mapping. 3. Apply operation-specific validation and security constraints. 4. Validate functional behavior across happy and negative paths.
Guardrails
- Keep API contract explicit and version-aware.
- Avoid exposing internal entity fields implicitly.
- Prevent drift between docs and actual serialization.
Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
Output contract
- API artifacts changed (resource/DTO/provider/processor).
- Contract/security decisions and rationale.
- Functional verification results.
References
reference.mddocs/complexity-tiers.md
API Platform DTO Resources Reference (Symfony)
Targets API Platform v4 (current 4.3). The biggest v3→v4 DTO change: `DataTransformerInterface` is gone (already removed by v3.4) and v4 introduces Symfony Object Mapper as the declarative mapping path.
Core idea
The #[ApiResource] class IS the DTO — the API contract — decoupled from your Doctrine entity. You map between the two either declaratively (Object Mapper, v4) or manually (custom provider/processor, works in both v3.4 and v4).
Strategy 1 (v4) — DTO resource + Object Mapper + stateOptions
Requires symfony/object-mapper:^7.4|^8.0. When the resource has stateOptions with an entityClass and both the DTO and entity carry #[Map], API Platform decorates the Doctrine provider/processor with the Object Mapper variants automatically.
<?php
// src/ApiResource/Book.php
namespace App\ApiResource;
use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Metadata\ApiResource;
use App\Entity\BookEntity;
use Symfony\Component\ObjectMapper\Attribute\Map;
#[ApiResource(
stateOptions: new Options(entityClass: BookEntity::class),
)]
#[Map(source: BookEntity::class)] // Entity → this DTO
final class Book
{
public ?int $id = null;
#[Map(source: 'title')] // BookEntity::$title → Book::$name
public string $name;
#[Map(transform: [self::class, 'formatPrice'])]
public string $price;
public static function formatPrice(int $cents): string
{
return number_format($cents / 100, 2) . ' €';
}
}Internal mapping classes engaged under the hood (no need to register them):
ApiPlatform\State\Provider\ObjectMapperProvider(reads)ApiPlatform\State\Processor\ObjectMapperProcessor(writes)
Options is ApiPlatform\Doctrine\Orm\State\Options.
#[Map] attribute (from symfony/object-mapper)
#[Map(source: 'field')]— Entity → DTO direction#[Map(target: 'field')]— DTO → Entity direction#[Map(transform: [Class::class, 'method'])]— custom transform callback
Strategy 2 (v4) — specialized input / output DTOs
Distinct shapes per operation, each #[Map]-bound to the entity:
<?php
use Symfony\Component\ObjectMapper\Attribute\Map;
#[Map(target: BookEntity::class)] // input → entity
final class CreateBook
{
#[Map(target: 'title')]
public string $name;
}
#[Map(source: BookEntity::class)] // entity → output
final class BookCollectionItem
{
#[Map(source: 'title')]
public string $name;
}use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Patch;
#[ApiResource(operations: [
new GetCollection(output: BookCollectionItem::class),
new Post(input: CreateBook::class),
new Patch(input: UpdateBook::class),
])]
final class Book {}Strategy 3 — custom processor business logic (v3.4 & v4)
When mapping needs real logic, do it explicitly in a processor (this is the only path in v3.4):
<?php
// src/State/DiscountBookProcessor.php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\ApiResource\Book;
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
final readonly class DiscountBookProcessor implements ProcessorInterface
{
public function __construct(private ObjectMapperInterface $objectMapper) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): Book
{
$entity = $context['request']->attributes->get('read_data');
$entity->price = (int) ($entity->price * (1 - $data->percentage / 100));
return $this->objectMapper->map($entity, Book::class);
}
}new Post(
uriTemplate: '/books/{id}/discount',
input: DiscountBook::class,
processor: DiscountBookProcessor::class,
)v3.4 approach (for comparison / legacy code)
v3.4 has no Object Mapper. You declare input / output and map manually inside a custom ProviderInterface (read) and ProcessorInterface (write):
// v3.4
#[Post(input: UserResetPasswordDto::class, processor: UserResetPasswordProcessor::class)]
final class User {}
#[Get(output: AnotherRepresentation::class, provider: BookRepresentationProvider::class)]
class Book {}DataTransformerInterface(transform()/supportsTransformation()) was the v2.x mechanism — already removed by v3.4. Do not reach for it; use providers/processors (v3.4) or Object Mapper (v4).
The manual provider/processor approach still works in v4 — Object Mapper is the new declarative shortcut, not a forced replacement.
Skill Operating Checklist
Design checklist
- Confirm operation boundaries and invariants first.
- Minimize scope while preserving contract correctness.
- Test both happy path and negative path behavior.
Validation commands
- ./vendor/bin/phpunit --filter=Api
- ./vendor/bin/phpstan analyse
- php bin/console debug:router
Failure modes to test
- Invalid payload or forbidden actor.
- Boundary values / not-found cases.
- Retry or partial-failure behavior for async flows.
Related skills
FAQ
Why use DTO resources in API Platform?
symfony:api-platform-dto-resources teaches DTO input and output objects so Symfony REST endpoints return stable JSON without exposing Doctrine entities. The skill prevents internal persistence models from leaking across API layers.
When should Symfony developers invoke this skill?
Developers should invoke symfony:api-platform-dto-resources when defining API Platform resources that need validated request DTOs and response DTOs. The makfly superpowers-symfony skill fits new endpoint design and entity decoupling refactors.