nelmio/api-doc-bundle
Symfony bundle to generate OpenAPI documentation for your APIs. Provides an interactive docs UI and schema generation driven by PHP 8 attributes. Requires PHP 8.1+ and Symfony 6.4+. Includes migration guides and solid CI support.
Installation:
composer require nelmio/api-doc-bundle
Ensure your config/bundles.php includes:
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
Enable Routes:
Add to config/routes.yaml:
nelmio_api_doc:
resource: "@NelmioApiDocBundle/Resources/config/routing.yaml"
prefix: /api/doc
First Use Case:
Annotate a controller method with #[OpenApi\Get]:
use OpenApi\Attributes as OA;
#[OA\Get(
path: "/users",
summary: "Get all users",
responses: [
new OA\Response(response: 200, description: "List of users")
]
)]
public function index(): array
{
return UserResource::collection(User::all());
}
Visit /api/doc to see the generated Swagger UI.
Attribute-Based Documentation:
Use OpenAPI attributes (#[OA\Get], #[OA\RequestBody], etc.) directly on controllers, DTOs, and entities.
Example for request body:
#[OA\RequestBody(
content: new OA\JsonContent(
type: "array",
items: new OA\Items(ref: "#/components/schemas/User")
)
)]
DTO Integration:
Document request/response models using #[OA\Schema]:
#[OA\Schema(
schema: "User",
type: "object",
properties: [
new OA\Property(property: "name", type: "string"),
new OA\Property(property: "email", type: "string", format: "email")
]
)]
class UserResource extends Resource
{
// ...
}
Route Grouping:
Use #[OA\Tag] to group related endpoints:
#[OA\Tag(name: "Users")]
#[OA\Get(path: "/users/{id}")]
public function show(User $user): UserResource
{
return new UserResource($user);
}
Security Schemes:
Define API keys or OAuth2 in config/packages/nelmio_api_doc.yaml:
nelmio_api_doc:
security_definitions:
api_key: { type: "apiKey", in: "header", name: "X-API-KEY" }
Dynamic Documentation:
Use #[OA\Operation] with operationId for dynamic route generation:
#[OA\Operation(operationId: "createUser")]
public function store(StoreUserRequest $request): UserResource
{
// ...
}
symfony/serializer is installed for DTO hydration.@ApiResource; combine both bundles for enhanced docs.nelmio_api_doc.components config:
nelmio_api_doc:
components:
schemas:
PaginatedResponse:
type: "object"
properties:
data: { type: "array" }
total: { type: "integer" }
Attribute vs. Annotation:
Nelmio 5.x requires PHP 8 attributes (not annotations). Update old @SWG\* to #[OA\*]:
- @SWG\Get(...)
+ #[OA\Get(...)]
Type Resolution:
type_info: true in config for better type hints:
nelmio_api_doc:
type_info: true
LegacyType (deprecated in 5.8+). Use Type from symfony/type-info.Route Conflicts:
#[Route] and #[OA\*] paths match exactly. Use #[OA\Operation] for dynamic routes:
#[OA\Operation(operationId: "deleteUser", summary: "Delete user")]
#[Route('/users/{id}', methods: ['DELETE'])]
Swagger UI Issues:
php bin/console cache:clear
File Uploads:
Combine #[MapRequestPayload] and #[MapUploadedFile] carefully (fixed in 5.9.4):
#[OA\RequestBody(
content: new OA\MultipartContent(
properties: [
new OA\Property(property: "file", type: "string", format: "binary")
]
)
)]
bin/console debug:nelmio-api-doc to inspect generated docs.nelmio_api_doc.yaml:
nelmio_api_doc:
debug: true
#[OA\Schema] with required: false for optional fields to avoid validation errors.Custom Describers:
Extend Nelmio\ApiDocBundle\Describer\DescriberInterface for custom type handling (e.g., Ulid support in 5.7.0).
Event Listeners:
Subscribe to Nelmio\ApiDocBundle\Event\DocumentationCompleteEvent to modify the OpenAPI spec:
use Nelmio\ApiDocBundle\Event\DocumentationCompleteEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CustomDocSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
DocumentationCompleteEvent::NAME => 'onDocumentationComplete',
];
}
public function onDocumentationComplete(DocumentationCompleteEvent $event): void
{
$event->getDocument()->info->title = 'Custom API Title';
}
}
Swagger UI Customization:
Override templates in templates/bundles/NelmioApiDoc/index.html.twig or use nelmio_api_doc.ui config:
nelmio_api_doc:
ui:
title: "My API Docs"
defaultModelsExpandDepth: -1
How can I help you explore Laravel packages today?