Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to separate out schema to keep controllers clean and focused on business logic? #2231

Open
Mir-Zairan opened this issue Mar 4, 2024 · 1 comment

Comments

@Mir-Zairan
Copy link

Background

I've successfully documented various API endpoints, and while the documentation functions correctly, I find that the presence of API documentation annotations clutters my controllers, leading to dissatisfaction with their readability and structure.

I tried to move schema to the nelmio_api_doc.yaml config file and then used ref to reference a particular schema. Although that did work but it still cluttered the nelmio_api_doc.yaml config file which I don't want. I would rather like to keep schema in a separate yaml or xml file and then somehow use that for providing a schema within the controller using ref or something else.

Example:

#[Route(path: '/save_entity', name: 'entity_api_save', methods: ['POST', 'PUT', 'PATCH'])]
#[OA\Tag(name: 'Entity Management')]
final class SaveEntity
{
    public function __construct(
    ) {}

    #[Areas(['entity_area'])]
    #[OA\RequestBody(
        description: 'Data needed to save or update the entity',
        required: true,
        content: new OA\MediaType(
            mediaType: 'application/json',
            schema: new OA\Schema(
                required: ['attribute1', 'attribute2', 'attribute3', 'attribute4', 'attribute5'],
                properties: [
                    new OA\Property(property: 'attribute1', type: 'string'),
                    new OA\Property(property: 'attribute2', type: 'string'),
                    new OA\Property(property: 'attribute3', type: 'string'),
                    new OA\Property(property: 'attribute4', type: 'string'),
                    new OA\Property(property: 'attribute5', type: 'string', nullable: true),
                    new OA\Property(property: 'additionalAttributes', type: 'array', items: new OA\Items(type: 'string')),
                ],
                type: 'object',
            )
        )
    )]
    #[OA\Response(
        response: 200,
        description: 'Entity saved successfully.',
        content: new OA\MediaType(
            mediaType: 'application/json',
            schema: new OA\Schema(
                type: 'array',
                items: new OA\Items(type: 'string', example: 'Entity saved successfully.')
            )
        )
    )]
    #[OA\Response(
        response: 400,
        description: 'Bad Request - Error in saving entity due to user error message.',
        content: new OA\MediaType(
            mediaType: 'application/json',
            schema: new OA\Schema(
                properties: [
                    new OA\Property(property: 'error', type: 'string', example: 'Localized error message'),
                ],
                type: 'object'
            )
        )
    )]
    public function __invoke(#[CurrentUser] UserInterface $user, Request $request): Response
    {}
}

Question:

Is there an alternative method to declutter the controllers by extracting these annotations, specifically the scheme part? I'm curious if it's possible to define these annotations in XML or YAML files and then integrate those files somehow to maintain the documentation separately.

Note:

Using @model is out of question!

@Mir-Zairan Mir-Zairan changed the title How to separate out documentation files to keep controllers clean and focused on business logic? How to separate out annotations to keep controllers clean and focused on business logic? Mar 4, 2024
@Mir-Zairan Mir-Zairan changed the title How to separate out annotations to keep controllers clean and focused on business logic? How to separate out schema to keep controllers clean and focused on business logic? Mar 5, 2024
@DjordyKoert
Copy link
Collaborator

You could try extending the ExternalDocDescriber and write your own logic.

class ExternalDocDescriber implements DescriberInterface

Or a PR would have to be made to support loading/appending the generated spec with some existing files through a configuration option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants