Efficience IT
·Formation

Swagger Nelmio Bundle et ses fonctionnalités : pourquoi l'utilise-t-on

Par Louis-Arnaud Catoire

Documenter une API est un acte fondateur. Ce n'est pas une corvée de fin de sprint, c'est le contrat qui lie le producteur de l'API à ses consommateurs. NelmioApiDocBundle permet de générer ce contrat directement depuis le code Symfony, sous forme d'une spécification OpenAPI exploitable par des humains et des machines. Cet article part des bases de la mise en place du bundle, puis explore les leviers avancés que les développeurs confirmés sous-exploitent souvent, avant d'aborder les questions d'architecture qui transforment la documentation en véritable outil de gouvernance.

La spécification OpenAPI en quelques mots

OpenAPI (anciennement Swagger Specification) est un standard industriel qui décrit une API REST dans un fichier JSON ou YAML. Ce fichier contient la liste des endpoints, les méthodes HTTP supportées, les schémas de requêtes et de réponses, les codes d'erreur et les mécanismes d'authentification. Des dizaines d'outils gravitent autour de ce format : Swagger UI pour la documentation interactive, Redoc pour une présentation plus éditoriale, et surtout des générateurs de SDK clients dans une trentaine de langages.

NelmioApiDocBundle est le pont entre l'écosystème Symfony et cette spécification. Il introspective les routes, les contrôleurs, les Form Types et les entités Doctrine pour produire un fichier OpenAPI sans écrire une ligne de YAML à la main.

Installation et configuration initiale

L'installation passe par Composer :

composer require nelmio/api-doc-bundle

Le fichier config/packages/nelmio_api_doc.yaml accueille la configuration centrale :

nelmio_api_doc:
    documentation:
        info:
            title: "Mon API"
            description: "Documentation de mon API"
            version: "1.0.0"
    areas:
        default:
            path_patterns:
                - ^/api

La directive areas est souvent ignorée par les débutants. Elle permet de segmenter la documentation en plusieurs zones : une pour l'API publique, une autre pour l'API d'administration, une troisième pour les webhooks. Chaque zone produit sa propre spécification OpenAPI, avec ses propres règles de sécurité.

Annoter les endpoints avec les attributs PHP 8

Depuis PHP 8, les attributs natifs remplacent avantageusement les annotations Doctrine. NelmioApiDocBundle supporte les attributs OpenApi du package nelmio/api-doc-bundle ainsi que ceux de OpenApi\Attributes :

#[Route('/api/users/{id}', methods: ['GET'])]
#[OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'))]
#[OA\Response(
    response: 200,
    description: 'Détail d\'un utilisateur',
    content: new OA\JsonContent(ref: new Model(type: User::class))
)]
#[OA\Response(response: 404, description: 'Utilisateur non trouvé')]
public function show(int $id): JsonResponse

Chaque attribut OA\Response documente un code HTTP de retour. Un endpoint bien documenté liste systématiquement les cas nominaux (200, 201) et les cas d'erreur (400, 403, 404, 422). Négliger les réponses d'erreur, c'est laisser les consommateurs deviner le comportement de l'API en cas de problème.

Documenter les modèles de données

Le véritable gain de productivité vient de la documentation automatique des modèles. Le bundle introspective les propriétés d'une classe PHP pour en déduire le schéma JSON :

class User
{
    #[OA\Property(description: 'Identifiant unique', example: 42)]
    public int $id;

    #[OA\Property(description: 'Adresse email', example: 'jean@example.com')]
    #[Assert\Email]
    public string $email;

    #[OA\Property(description: 'Date de création', example: '2024-01-15T10:30:00+00:00')]
    public \DateTimeImmutable $createdAt;
}

Le bundle exploite également les contraintes de validation Symfony (Assert\NotBlank, Assert\Length, Assert\Email) pour enrichir le schéma avec des règles required, minLength, maxLength et format. Résultat : la documentation reflète fidèlement les règles métier sans duplication.

Pour les structures complexes impliquant de l'héritage ou du polymorphisme, les attributs OA\Discriminator et OA\OneOf permettent de représenter des unions de types. Un endpoint qui retourne soit un InternalUser soit un ExternalPartner peut le documenter proprement, évitant le piège du schéma fourre-tout.

Schémas de sécurité

La configuration des schémas de sécurité dans NelmioApiDocBundle couvre les cas courants : clé API, Bearer JWT et OAuth2. Voici une configuration JWT typique :

nelmio_api_doc:
    documentation:
        components:
            securitySchemes:
                Bearer:
                    type: http
                    scheme: bearer
                    bearerFormat: JWT
        security:
            - Bearer: []

La directive security au niveau racine applique l'authentification à tous les endpoints par défaut. Pour les endpoints publics (login, healthcheck), l'attribut #[OA\Security(name: null)] désactive explicitement la sécurité sur un contrôleur donné. Cette approche secure-by-default est préférable à l'inverse, où chaque endpoint doit déclarer manuellement sa sécurité.

Pour les architectures multi-tenants ou les API B2B, OAuth2 avec ses différents flows (authorization_code, client_credentials) se configure de la même manière dans la section securitySchemes. La documentation devient alors le reflet exact de la politique de sécurité.

Versionner la documentation API

Sur les projets matures, plusieurs versions de l'API cohabitent. NelmioApiDocBundle gère ce besoin via les areas combinées au préfixage des routes :

nelmio_api_doc:
    areas:
        v1:
            path_patterns:
                - ^/api/v1
        v2:
            path_patterns:
                - ^/api/v2

Chaque area produit une spec OpenAPI distincte, accessible via son propre endpoint (/api/doc/v1, /api/doc/v2). Les consommateurs de l'API v1 ne voient pas les endpoints v2, et inversement. Cette séparation nette évite la confusion et permet de planifier la dépréciation progressive des anciennes versions.

Contract-first vs code-first : un choix d'architecture

NelmioApiDocBundle incarne l'approche code-first : on écrit le code PHP, le bundle en déduit la spécification OpenAPI. Cette approche convient à la majorité des projets Symfony, notamment les API internes ou les projets où l'équipe backend contrôle le rythme.

L'approche inverse, contract-first, consiste à rédiger la spécification OpenAPI avant d'écrire la moindre ligne de code. Le fichier YAML devient le livrable du design review, validé par les équipes front, mobile et partenaires avant que le développement ne commence. Des outils comme jane-php/open-api génèrent ensuite le squelette PHP depuis la spec.

En pratique, les architectures hybrides fonctionnent bien : on démarre contract-first pour les nouvelles API exposées à des tiers, et on utilise NelmioApiDocBundle en code-first pour les API internes. Le point de convergence reste le fichier OpenAPI, quelle que soit la méthode qui l'a produit.

Gouvernance API et documentation comme source de vérité

À l'échelle d'une organisation qui expose plusieurs dizaines d'API, la documentation cesse d'être un livrable optionnel pour devenir un artefact de gouvernance. La spécification OpenAPI générée par NelmioApiDocBundle sert de socle à plusieurs processus critiques.

Validation en CI

Le fichier OpenAPI exporté peut être validé à chaque commit par des outils comme spectral ou openapi-diff. Une règle CI typique vérifie que chaque endpoint possède au moins une réponse d'erreur documentée, que tous les paramètres ont une description, et qu'aucun breaking change n'a été introduit entre deux versions :

spectral lint openapi.json --ruleset .spectral.yaml
openapi-diff openapi-previous.json openapi-current.json --fail-on-incompatible

Cette validation automatisée attrape les régressions de documentation avant qu'elles n'atteignent la production. Un endpoint sans description ou un schéma modifié sans bump de version devient un build cassé, au même titre qu'un test unitaire en échec.

Génération de SDK clients

La spécification OpenAPI alimente directement les générateurs de SDK. OpenAPI Generator produit des clients typés en TypeScript, Kotlin, Swift ou Python à partir du même fichier JSON. Les équipes front-end et mobile n'ont plus à interpréter la documentation : elles importent un package généré, avec l'autocomplétion et le typage garantis par le schéma.

Ce flux (code PHP → spec OpenAPI → SDK client) transforme la documentation en contrat exécutable. Une modification du schéma côté backend casse la compilation du SDK client, ce qui force une coordination explicite entre les équipes. C'est exactement le comportement souhaité : les breaking changes deviennent impossibles à ignorer.

Tests de contrat

Les spécifications OpenAPI servent également de base pour les tests de contrat. Des bibliothèques comme league/openapi-psr7-validator interceptent les requêtes et réponses HTTP en test pour vérifier leur conformité avec la spec. Si un contrôleur retourne un champ supplémentaire non documenté ou omet un champ obligatoire, le test échoue. La documentation et l'implémentation restent synchronisées par construction, pas par discipline.

La documentation comme produit

Pour un architecte, la question n'est pas de savoir si NelmioApiDocBundle fonctionne, c'est de savoir où il s'inscrit dans la chaîne de valeur. Une API dont la documentation est générée automatiquement, validée en CI, utilisée pour produire des SDK et vérifiée par des tests de contrat n'est plus un simple endpoint HTTP. C'est un produit logiciel dont la surface contractuelle est maîtrisée de bout en bout.

NelmioApiDocBundle est la première brique de cette chaîne dans l'écosystème Symfony. Son adoption est triviale, mais son potentiel se révèle pleinement quand il s'intègre dans une stratégie de gouvernance API plus large : areas par audience, sécurité par défaut, validation automatisée et génération de SDK.

Pour aller plus loin