nelmio/api-doc-bundle
NelmioApiDocBundle generates clean, accurate API documentation for your Symfony applications using PHP 8 attributes and OpenAPI 3.0, with support for FrankenPHP worker mode and long-running workers.
Architecture fit. The first finding a TPM must escalate is categorical: nelmio/api-doc-bundle is a Symfony bundle, not a Laravel package. It boots via a Symfony DI extension, registers tagged services (PropertyDescriberInterface, model describers, area describers), and hooks the kernel — there is no service provider, no facade, no Laravel package discovery. In a Laravel codebase it will not install or boot cleanly. If the target stack is Laravel, the correct architectural comparison set is dedoc/scramble (runtime route introspection) or darkaonline/l5-swagger (swagger-php wrapper), and this package should be rejected on fit rather than on quality. If the target is Symfony 6.4+/7.x with PHP 8.1+, this is close to the reference implementation for code-first OpenAPI generation from PHP 8 attributes.
Integration feasibility. Assuming Symfony, feasibility is high: one composer require, a config/packages/nelmio_api_doc.yaml block defining areas, and an #[OA\...]/#[Model] annotation pass over controllers and DTOs. The bundle is deliberately thin on opinion — it produces the OpenAPI document and serves a bundled UI (Swagger UI, ReDoc, Stoplight Elements, or Scalar as of 5.10). The real effort is not installation, it is the annotation backlog across every endpoint and model, plus configuration of areas if the API surface is multi-version or multi-audience.
Technical risk.
with_annotation → with_attribute, Areas array-key shape, Model::$options nullability). Manageable only with a CI deprecation gate.Key questions.
Stack fit. Symfony 6.4/7.1+, PHP 8.1+, Symfony Serializer or JMS Serializer for model description, Doctrine entities or DTOs as schemas, zircote/swagger-php ^5.7.8/^6.0 underneath. Optional integration points worth planning for: #[IsGranted]-derived security schemes (5.2.0), MapQueryParameter with regex conversion to ECMA-262 (4.38.2), MapUploadedFile (4.38.0), TranslatableInterface (5.3.0), and symfony/type-info (4.35.0). If any of these appear in our controllers, they are cheap wins; if our auth is a custom middleware rather than Symfony security, the security-scheme automation will not apply and must be hand-declared.
Migration path. Two distinct migrations, budget them separately:
Compatibility. Pin the bundle minor and let Composer resolve; the 5.x line ships frequently. Watch three seams: the Symfony minor floor, the swagger-php major, and the bundled front-end asset versions (Swagger UI/ReDoc/Scalar/Stoplight are vendored into /utils and bumped almost every release — this shows up as lockfile and static-asset churn, not PHP risk).
Sequencing.
#[Model] — validate generated JSON against an OpenAPI 3 validator.Maintenance. Healthy: MIT, active CI with Codecov, frequent patch/minor releases, corporate sponsorship, and explicit upgrade guides per major. Vendor risk is low; the ongoing cost is annotation upkeep — every endpoint change now has a documentation obligation, and that obligation is unenforced by the framework. Budget it as a standing tax, not a one-off project.
Support. Community-only. Issues are handled on GitHub with no SLA; the authoritative documentation lives on symfony.com rather than the repo. We need an internal owner who understands describers and areas, because escalations will land on us.
Scaling. Generation cost scales with model-graph size and number of areas — expect slow cold generation on large entities, mitigated by caching/warmup. The served UI is static assets, effectively free at runtime but a public information-disclosure surface: gate it. 5.11.1 specifically hardened generation for FrankenPHP and long-running workers, so state bleed across requests is a known-and-addressed class of bug — pin at or above that.
Failure modes to instrument for. (a) Silent drift between attributes and actual behavior — mitigated by the CI diff gate but not eliminated; (b) schema deduplication collisions across namespaces — FQCN keying landed in 5.10, older pins can merge distinct models; (c) nullable/oneOf mis-wrapping in the JMS describer (5.10 fix); (d) root-level vendor extensions being dropped (5.10.2); (e) generation exceptions taking out the docs route or, worse, CI; (f) framework upgrade blocked by the bundle's Symfony floor.
Ramp-up. For a Symfony-fluent engineer, one to two days to first productive spec, roughly a week to own areas, describers, and security schemes. Non-trivial prerequisite knowledge: OpenAPI 3.0 semantics and Symfony DI/tagged services. For a Laravel-only team, ramp-up is not the issue — the framework mismatch is, and time spent here is better redirected to dedoc/scramble.
Recommendation. Adopt if and only if the API is Symfony 6.4+/PHP 8.1+. Reject for Laravel on architecture fit, not on package quality. Either way, make the CI drift gate and docs-route authentication part of the initial scope rather than a follow-up — they are the difference between a documentation system and a stale liability.
How can I help you explore Laravel packages today?