oro/api-doc-bundle
Fork of NelmioApiDocBundle 2.x updated for Symfony 5 compatibility. Generates API documentation with a Swagger-UI-inspired interface, including routes, parameters, and responses, with PHPUnit tests and MIT license.
Install Dependencies: Since this is a Symfony bundle, install it alongside Symfony components for compatibility:
composer require oro/api-doc-bundle symfony/serializer symfony/http-kernel
Configure Laravel to Use Symfony Components:
Add Symfony’s HttpKernel and Serializer to Laravel’s service provider:
// config/app.php
'providers' => [
// ...
Symfony\Component\HttpKernel\HttpKernelBundle\HttpKernelBundle::class,
Symfony\Component\Serializer\SerializerBundle\SerializerBundle::class,
],
Basic Bundle Setup: Create a custom service provider to bridge Symfony and Laravel:
php artisan make:provider NelmioApiDocServiceProvider
Register the bundle in register():
use Oro\ApiDocBundle\NelmioApiDocBundle;
use Symfony\Component\HttpKernel\Kernel;
public function register()
{
if (!class_exists(Kernel::class)) {
$this->app->register(Symfony\Component\HttpKernel\HttpKernelBundle\HttpKernelBundle::class);
}
$this->app->register(NelmioApiDocBundle::class);
}
First Use Case: Annotate a Laravel controller to generate API docs:
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Annotation\Model;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class UserController extends Controller
{
/**
* @Route("/users/{id}", name="get_user", methods={"GET"})
* @ApiDoc(
* description="Get a user by ID",
* resource=true,
* requirements={
* {"name"="id", "dataType"="integer", "requirement"="\d+"}
* },
* statusCodes={
* 200={"description"="User found"},
* 404={"description"="User not found"}
* }
* )
* @Model(type="App\Entity\User", groups={"user_read"})
*/
public function getUser(int $id)
{
return User::findOrFail($id);
}
}
Access Documentation: Add a route to serve the NelmioApiDocBundle UI:
Route::get('/api/doc', [NelmioApiDocBundle::class, 'indexAction']);
Visit /api/doc to see the interactive API documentation.
Annotation-Driven Documentation:
@ApiDoc, @Route, and @Model annotations to document controllers, routes, and entities./**
* @Route("/users", name="create_user", methods={"POST"})
* @ApiDoc(
* description="Create a new user",
* input="App\\Dto\\CreateUserDto",
* statusCodes={
* 201={"description"="User created"},
* 400={"description"="Invalid input"}
* }
* )
*/
public function createUser(Request $request)
{
// ...
}
Entity Documentation:
@Model to document entity fields and groups:
/**
* @Model(
* type="App\Entity\User",
* groups={"user_read", "user_write"}
* )
*/
class User {}
Security Schemes:
nelmio_api_doc.yaml:
nelmio_api_doc:
documentation:
securityDefinitions:
api_key:
type: "apiKey"
in: "header"
name: "X-API-KEY"
Customizing the UI:
vendor/nelmio/api-doc-bundle/Resources/views/SwaggerBundle/index.html.twig to resources/views/vendor/nelmio_api_doc/index.html.twig.Laravel Route Integration:
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route annotations alongside Laravel’s Route attributes:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Routing\Annotation\Route as SymfonyRoute;
/**
* @SymfonyRoute("/users/{id}", name="get_user")
* @Route(name: "get_user", path: "/users/{id}", methods: ["GET"])
*/
Symfony Serializer for Request/Response:
Serializer to handle Laravel’s data structures:
$serializer = Serializer::create([
new XmlSerializer(),
new JsonSerializer(),
new ObjectNormalizer(),
], [new DateTimeNormalizer()]);
Caching Generated Docs:
$cache = new FileCache(sys_get_temp_dir());
$generator = new OpenApiGenerator($cache);
Validation:
zircote/swagger-php.Testing:
public function testApiDocAnnotations()
{
$reflection = new \ReflectionClass(UserController::class);
$annotations = $reflection->getMethod('getUser')->getAnnotations();
$this->assertArrayHasKey('ApiDoc', $annotations);
}
Symfony-Specific Dependencies:
HttpKernel, EventDispatcher, and Serializer.spatie/laravel-annotation-reader instead of SensioFrameworkExtraBundle.Annotation Parsing Conflicts:
doctrine/annotations may not fully support Symfony’s annotation format.doctrine/annotations and configure it to read PHPDoc comments:
$annotationReader = new \Doctrine\Common\Annotations\AnnotationReader();
$annotationReader->addNamespace('Nelmio\ApiDocBundle\Annotation');
Route Collection Mismatch:
RouteCollection, but Laravel uses its own router.$routeCollection = new RouteCollection();
foreach (Route::getRoutes() as $route) {
$symfonyRoute = new Route(
$route->uri(),
new RequestContext(),
new RouteCollection()
);
$routeCollection->add($route->getName(), $symfonyRoute);
}
Circular Dependencies:
$this->app->singleton(Symfony\Component\Serializer\SerializerInterface::class, function () {
return Serializer::create([/* ... */]);
});
Deprecated Annotations:
@ApiResource) may be deprecated in newer versions.@ApiDoc.Performance with Large APIs:
Enable Debug Mode:
nelmio_api_doc.debug: true in nelmio_api_doc.yaml to see detailed errors.Check Generated Schema:
/api/doc.json to inspect the raw OpenAPI schema for errors.Validate Annotations:
phpdoc/parser to validate annotations before runtime:
$parser = new \phpDocumentor\Reflection\DocBlockFactory();
$docBlock = $parser->create($reflectionMethod);
Symfony Event Listeners:
kernel.request), ensure they’re properly bound to Laravel’s event system:
Event::listen('kernel.request', function ($request) {
// Adapt Symfony event logic here
});
class CustomAnnotationHandler extends AbstractAnnotationHandler
{
public function getAnnotationName()
{
return 'CustomAnnotation';
}
public function handle(Annotation $annotation, Controller
How can I help you explore Laravel packages today?