You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API Platform 3中POST/PUT请求如何实现DTO输入与输出?

API Platform 3 写入操作同时使用不同输入输出DTO的实现方案

API Platform 3完全支持你需要的「写入操作同时使用与资源不同的输入和输出DTO」场景,你需要在资源注解中同时配置input、output,并为写入操作指定自定义State Processor和State Provider,完整流程可复现API Platform 2中DataTransformer的逻辑。

1. 资源类注解配置

在实体的ApiResource注解中,针对写入操作(如POST、PUT)同时指定输入DTO、输出DTO,以及对应的Processor和Provider:

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Get;

#[ApiResource(
    operations: [
        new Post(
            input: InputDto::class,
            output: OutputDto::class,
            processor: EntityWriteProcessor::class,
            provider: EntityReadProvider::class
        ),
        new Put(
            input: InputDto::class,
            output: OutputDto::class,
            processor: EntityWriteProcessor::class,
            provider: EntityReadProvider::class
        ),
        new Get(
            output: OutputDto::class,
            provider: EntityReadProvider::class
        )
    ]
)]
class YourEntity
{
    // 实体字段定义
}

2. 自定义State Processor(处理输入DTO转实体)

Processor负责接收输入DTO,将其转换为实体,执行业务逻辑(如持久化)后返回实体,供后续Provider转换为输出DTO:

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use Doctrine\ORM\EntityManagerInterface;

class EntityWriteProcessor implements ProcessorInterface
{
    public function __construct(private readonly EntityManagerInterface $entityManager) {}

    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): YourEntity
    {
        // 1. 输入DTO转实体
        $entity = new YourEntity();
        $entity->setTitle($data->getTitle());
        $entity->setContent($data->getContent());
        // 其他字段映射逻辑

        // 2. 执行实体处理(持久化等)
        $this->entityManager->persist($entity);
        $this->entityManager->flush();

        // 3. 返回实体,交由Provider转换为输出DTO
        return $entity;
    }
}

3. 自定义State Provider(处理实体转输出DTO)

Provider负责接收Processor返回的实体(或从数据库查询实体),将其转换为输出DTO并返回:

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use Doctrine\ORM\EntityManagerInterface;

class EntityReadProvider implements ProviderInterface
{
    public function __construct(private readonly EntityManagerInterface $entityManager) {}

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): OutputDto
    {
        // 获取目标实体:写入操作中可通过$context['data']获取Processor返回的实体,GET操作通过ID查询
        $entity = $context['data'] ?? $this->entityManager->getRepository(YourEntity::class)->find($uriVariables['id']);

        // 实体转输出DTO
        $outputDto = new OutputDto();
        $outputDto->setId($entity->getId());
        $outputDto->setDisplayTitle($entity->getTitle());
        $outputDto->setPreviewContent(substr($entity->getContent(), 0, 100));
        // 其他字段映射逻辑

        return $outputDto;
    }
}

关键注意事项

  • 写入操作必须同时指定provider,否则API Platform会直接返回Processor输出的实体,而非配置的输出DTO
  • 可以使用AutoMapper、MapStruct等工具简化DTO与实体之间的映射,减少手动赋值代码
  • 若需要处理集合类型的输出(如GET列表),需在Provider中添加集合转换逻辑

内容的提问来源于stack exchange,提问作者Dave Small

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:52:53