noma-solutions/api-doc-bundle
A Symfony bundle that turns your API endpoints into clear, browsable documentation. Generates docs from routes and controllers, supports customization, and helps keep reference docs in sync with your code.
Read this first: the package is a Symfony bundle, not a Laravel package. noma-solutions/api-doc-bundle is a fork of NelmioApiDocBundle — it generates OpenAPI/Swagger docs from PHP annotations/attributes and is wired through Symfony's DI container and routing conventions. There is no service provider, no config/api-doc.php, and no artisan command.
Minimal evaluation steps for a Laravel developer:
composer require noma-solutions/api-doc-bundle in a throwaway Laravel 10/11 app and observe the dependency conflict. It will pull in symfony/http-kernel, symfony/config, symfony/routing, and zircote/swagger-php, and typically fails resolution or installs a tree Laravel cannot bootstrap.src/Annotation/ (or src/Attribute/) and src/Model/ in the fork to understand how it maps docblocks to OpenAPI operations. That is the only part that transfers usefully to Laravel.First realistic use case in Laravel: don't adopt this bundle. Use it as a reference implementation and port the pattern to one of the Laravel-native options:
zircote/swagger-php directly (or via darkaonline/l5-swagger) — same #[OA\Info], #[OA\Get], #[OA\Schema] attribute syntax the fork is built around.dedoc/scramble — zero-annotation, infers specs from routes, form requests, and resources.knuckleswtf/scribe — annotation-driven plus HTML output, closer in spirit to Nelmio's UI.If you are genuinely maintaining a Symfony app alongside a Laravel one, the fork is still a poor choice: depend on nelmio/api-doc-bundle upstream, which has actual releases and issue history.
Symfony pattern (what the bundle actually supports). Config lives in config/packages/nelmio_api_doc.yaml. Routes are registered under _nelmio_api_doc and served at /api/doc and /api/doc.json. Annotations are added to controllers:
#[OA\Get(path: '/users/{id}', summary: 'Fetch a user')]
#[OA\Parameter(name: 'id', in: 'path', required: true)]
public function show(int $id): Response { ... }
The bundle's job is to collect those, merge them with route metadata, and emit an OpenAPI 3 document — the OpenAPI model itself comes from zircote/swagger-php.
Laravel translation of that pattern. The annotations are portable; the bundle plumbing is not.
composer require darkaonline/l5-swagger
php artisan vendor:publish --provider="L5Swagger\L5SwaggerServiceProvider"
Then annotate the same way:
/**
* @OA\Get(
* path="/api/users/{id}",
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"))
* )
*/
public function show(User $user) { ... }
Run php artisan l5-swagger:generate in CI and commit storage/api-docs/api-docs.json so spec drift shows up as a diff.
Workflow patterns worth copying from the bundle's design:
#[OA\Info] / @OA\Info once on a dedicated OpenApiSpec class rather than repeating it per controller.#[OA\Schema] on Eloquent API Resources and reference them with $ref, mirroring how Nelmio users annotate Symfony serializers.Users, Billing, Admin) so the Swagger UI stays navigable as the API grows.nelmio:apidoc:dump does.Migration path if you have an existing Symfony codebase using this fork. Strip the #[Nelmio\...] namespace-only annotations (there usually are none — Nelmio reuses OpenApi\Annotations), copy the annotation blocks verbatim into Laravel controllers, and replace config/packages/nelmio_api_doc.yaml with config/l5-swagger.php. Roughly 90% of the annotation content survives; 0% of the wiring does.
composer.json pins Symfony components and expects symfony/framework-bundle. Expect Conclusion: don't install laravel/framework or a "requires symfony/routing ^5.4|^6.0" conflict. Forcing it with --ignore-platform-reqs just moves the failure to boot time.NelmioApiDocBundle::boot() or its DependencyInjection\NelmioApiDocExtension. You'd have to manually register the extension on a Symfony container — which Laravel doesn't have.composer.json against nelmio/api-doc-bundle@main. If it pins an old zircote/swagger-php (2.x or early 3.x), the annotation syntax differs meaningfully from what current L5-Swagger expects — @OA\ vs #[OA\, @SerializedName behavior, nullable handling.Resources/public/. This is the piece people actually want, and it's the piece most likely to be stale and unpatched in a 0-star fork. Use the official Swagger UI or Redoc bundle via L5-Swagger instead.areas, documentation.info, models.naming_strategy, and html_format are Nelmio concepts with no L5-Swagger equivalent; you'll approximate them with @OA\Server, @OA\Tag, and multiple L5_SWAGGER_... env vars or separate config files per API version.bin/console nelmio:apidoc:dump --format=json was the fast feedback loop. Your Laravel equivalent is php artisan l5-swagger:generate and inspecting storage/api-docs/api-docs.json, or hitting /api/documentation for the UI.ModelDescriber / ApiDocGenerator interfaces are the seam Symfony users customize for custom serializer types. In Laravel, the equivalent seam is a custom OpenApi\Attributes\Schema generator or a Scramble extension — that's where you'd hook custom casts (money, enums, encrypted columns) so the spec reflects reality.api-docs.json changes without a corresponding commit. This single rule catches ~80% of undocumented-route drift in Laravel projects and is the habit Nelmio users rely on most.How can I help you explore Laravel packages today?