首页 > 解决方案 > 为 API 平台中的自定义操作禁用 requestBody

问题描述

我想为没有参数的自定义 POST 路由操作禁用 openapi 的 requestBody 文档。为此,我尝试像这样扩展 openapi_context:

/*
 * @ApiResource(
 *     ...
 *     itemOperations={
 *         ...
 *         "post_clone" = {
 *             ...
 *             "openapi_context"={
 *                 "requestBody"=null
 *             }
 *         }
 *     }
 * )
 */

将 requestBody 设置为nullorfalse与跳过该值相同,并导致 POST 路由的默认文档。将 requestBody 设置为{}在文档中写入空对象,但我需要的是在文档中跳过该键。

标签: api-platform.com

解决方案


你以错误的方式实施你的clone操作。POST操作是集合操作,而不是项目操作。即使今天您能够将POST操作声明为项目操作,它也更有可能是 API 平台的副作用,而不是预期的行为。

为了尊重 API-Platform 生命周期,我建议您执行以下操作:

首先,将您的clone操作声明为 POST 集合操作,使用命名为DTO 作为输入MyEntityCloneDto

use App\Dto\MyEntityCloneDto;

/**
 * @ApiResource(
 *     collectionOperations={
 *          "get",
 *          "post",
 *          "clone" = {
 *              "method" = "post",
 *              "path" = "/my_entities/clone",
 *              "input" = MyEntityCloneDto::class,
 *          }
 *     }
 * )
 * @ORM\Entity(repositoryClass=MyEntityRepository::class)
 */
class MyEntity

然后创建输入 DTO:

namespace App\Dto;

use App\Entity\MyEntity;
use Symfony\Component\Validator\Constraints as Assert;

class MyEntityCloneDto
{
    /**
     * The entity to clone.
     *
     * @Assert\NotNull()
     */
    public ?MyEntity $myEntity = null;
}

最后创建DataTransformer

namespace App\DataTransformer;

use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use App\Entity\MyEntity;
use ApiPlatform\Core\Validator\ValidatorInterface;

class MyEntityCloner implements DataTransformerInterface
{
    private ValidatorInterface $validator;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    public function transform($object, string $to, array $context = [])
    {
        $this->validator->validate($object);
        return clone $object->myEntity; //add more logic if needed of course
    }

    public function supportsTransformation($data, string $to, array $context = []): bool
    {
        return MyEntity::class === $to;
    }
}

MyEntity使用 ID 5 进行克隆:

curl --request POST \
    --header 'content-type: application/json' \
    --header 'accept: application/ld+json' \
    --data '{"myEntity": "/my_entities/5"}' \
    http://example.com/api/my_entities/clone

这样,OpenAPI视图显示真相并且您的操作保持稳定。

请注意,如果您需要clone对所有实体进行操作,则可以重新使用数据转换器,因为它的方法没有类型化。但是为了制作Serializer作品,每个实体都需要一个 DTO,因为它需要知道要克隆的实体的类型。


推荐阅读