API 平台的自定义 GET 操作生成错误的文档

Custom GET operation for API platform generates wrong documentation

我在TeachingClass实体下添加了如下操作

App\Entity\TeachingClass:
    collectionOperations:
        # ...
    itemOperations:
        # ...

        get_learning_skills:
            method: GET
            path: /auth/v1/teaching-class/{id}/learning-skills
            resourceClass: 'App\Entity\LearningSkill' # Doesn't seem to work
            controller: App\Controller\Api\LearningSkillApiController
            normalization_context:
                groups: ['learning_skill_list']
            security: 'is_granted("HAS_TEACHING_CLASS_ACCESS", object)'
            swagger_context:
                summary: "Retrieves the collection of LearningSkill resources belonging to a specific TeachingClass."
                description: "LearningSkills belonging to a specific TeachingClass"

端点正确 returns 配置控制器的 LearningSkill 实体集合:

<?php

namespace App\Controller\Api;

use App\Entity\LearningSkill;
use App\Entity\TeachingClass;
use App\Repository\LearningSkillRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * Class LearningSkillApiController.
 */
class LearningSkillApiController
{
    private $learningSkillRepository;

    public function __construct(LearningSkillRepository $learningSkillRepository)
    {
        $this->learningSkillRepository = $learningSkillRepository;
    }

    public function __invoke(TeachingClass $data)
    {
        return $this->byTeachingClass($data);
    }

    private function byTeachingClass(TeachingClass $teachingClass)
    {
        return $this->learningSkillRepository->findByTeachingClass($teachingClass);
    }
}

但是,我的问题是生成的API文档是错误的:

如何使文档反映响应是 LearningSkill 实体的集合(而不是 TeachingClass 实体)?

我的 tutorial 的 chapter9-api 分支中的报告也有同样的问题,它输出 DayTotalsPerEmployee 的实例,而不是端点打开的 class。我的解决方案是制作一个 SwaggerDecorator。以下是适合您的操作。

它还设置响应 200 内容引用的组件架构中的描述。这是基于您的响应是收集响应的假设。它 apip 认为这是一个项目响应,可能需要做更多的工作才能使 swagger 文档描述一个集合响应。

<?php

namespace App\Swagger;

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

final class SwaggerDecorator implements NormalizerInterface
{
    private $decorated;

    public function __construct(NormalizerInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function normalize($object, string $format = null, array $context = [])
    {
        $summary = 'The collection of LearningSkill resources belonging to a specific TeachingClass.';
        $docs = $this->decorated->normalize($object, $format, $context);

        $docs['paths']['/auth/v1/teaching-class/{id}/learning-skills']['get']['responses']['200']['description'] = 'LearningSkills collection response';

        $responseContent = $docs['paths']['/auth/v1/teaching-class/{id}/learning-skills']['get']['responses']['200']['content'];
        $this->setByRef($docs, $responseContent['application/ld+json']['schema']['properties']['hydra:member']['items']['$ref'],
            'description', $summary);
        $this->setByRef($docs, $responseContent['application/json']['schema']['items']['$ref'],
            'description', $summary);

        return $docs;
    }

    public function supportsNormalization($data, string $format = null)
    {
        return $this->decorated->supportsNormalization($data, $format);
    }

    private function setByRef(&$docs, $ref, $key, $value)
    {
        $pieces = explode('/', substr($ref, 2));
        $sub =& $docs;
        foreach ($pieces as $piece) {
            $sub =& $sub[$piece];
        }
        $sub[$key] = $value;
    }
}

要配置服务,请将以下内容添加到 api/config/services.yaml:

'App\Swagger\SwaggerDecorator':
    decorates: 'api_platform.swagger.normalizer.api_gateway'
    arguments: [ '@App\Swagger\SwaggerDecorator.inner' ]
    autoconfigure: false