在 API 平台中禁用自定义操作的 requestBody

Disable requestBody for custom action in API Platform

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

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

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

您执行 clone 操作的方式有误。 POST操作是collection operations,不是物品操作。即使今天您能够将 POST 操作声明为项目操作,它更可能是 API-平台的副作用,而不是预期的行为。

为了尊重API-平台生命周期,我建议您做以下事情:

首先,将您的clone操作声明为POST集合操作,使用as input 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;
    }
}

使用 ID 5 克隆 MyEntity

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,因为它需要知道要克隆的实体的类型。