Skip to content

Automatic OpenAPI 3.0 specification generator from routes and DTOs. Extracts API documentation from code using PHP 8 attributes, Symfony Validator constraints, and PSR-15 middleware. JSON/YAML output, zero configuration. Framework-agnostic, CLI integration.

License

Notifications You must be signed in to change notification settings

MethorZ/openapi-generator

Repository files navigation

MethorZ OpenAPI Generator

Automatic OpenAPI 3.0 specification generator from routes and DTOs

PHP Version License

Automatically generates OpenAPI specifications by analyzing your application's routes and Data Transfer Objects (DTOs). Perfect for Mezzio, Laminas, and any PSR-15 application.


✨ Features

  • 🚀 Automatic Generation: Scans routes and DTOs to generate complete OpenAPI specs
  • 📝 DTO Analysis: Extracts request/response schemas from PHP DTOs with property promotion
  • Validation Integration: Reads Symfony Validator attributes for schema constraints
  • 🎯 Handler Detection: Automatically finds request and response DTOs in handlers
  • 📦 Multiple Formats: Generates both YAML and JSON outputs
  • 🔧 Zero Configuration: Works out-of-the-box with sensible defaults
  • 🎨 Customizable: Configure via application config
  • 🔗 Nested DTOs: Automatically generates schemas for nested DTO references
  • 📚 Collections: Supports typed arrays with @param array<Type> PHPDoc
  • 🎲 Enums: Full support for backed and unit enums (PHP 8.1+)
  • 🔀 Union Types: Generates oneOf schemas for union types (PHP 8.0+)
  • Performance: Schema caching for efficient generation

📦 Installation

composer require methorz/openapi-generator

🚀 Quick Start

1. Register the Command

Add to your application's command configuration:

// config/autoload/dependencies.global.php use Methorz\OpenApi\Command\GenerateOpenApiCommand; return [ 'dependencies' => [ 'factories' => [ GenerateOpenApiCommand::class => function ($container) { return new GenerateOpenApiCommand($container); }, ], ], ];

2. Generate Specification

php bin/console openapi:generate

This will create:

  • public/openapi.yaml - YAML format
  • public/openapi.json - JSON format

📖 Usage

Basic Configuration

// config/autoload/openapi.global.php return [ 'openapi' => [ 'title' => 'My API', 'version' => '1.0.0', ], ];

Example Handler

The generator automatically analyzes your handlers:

namespace App\Handler; use App\Request\CreateItemRequest; use App\Response\ItemResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; final class CreateItemHandler implements RequestHandlerInterface { public function handle( ServerRequestInterface $request, CreateItemRequest $dto // ← Request DTO detected ): ItemResponse { // ← Response DTO detected // Handler logic... } }

Example Request DTO

namespace App\Request; use Symfony\Component\Validator\Constraints as Assert; final readonly class CreateItemRequest { public function __construct( #[Assert\NotBlank] #[Assert\Length(min: 3, max: 100)] public string $name, #[Assert\NotBlank] #[Assert\Length(min: 10, max: 500)] public string $description, #[Assert\Email] public string $email, ) {} }

Generated Schema:

components: schemas: CreateItemRequest: type: object required: - name - description - email properties: name: type: string minLength: 3 maxLength: 100 description: type: string minLength: 10 maxLength: 500 email: type: string format: email

📋 Supported Validation Attributes

The generator extracts constraints from Symfony Validator attributes:

Attribute OpenAPI Property
@Assert\NotBlank required: true
@Assert\Length(min, max) minLength, maxLength
@Assert\Range(min, max) minimum, maximum
@Assert\Email format: email
@Assert\Url format: uri
@Assert\Uuid format: uuid

🚀 Advanced Features

Enum Support

Generates enum schemas from PHP 8.1+ backed enums:

enum StatusEnum: string { case DRAFT = 'draft'; case ACTIVE = 'active'; case ARCHIVED = 'archived'; } final readonly class CreateItemRequest { public function __construct( public StatusEnum $status, ) {} }

Generated Schema:

CreateItemRequest: type: object properties: status: type: string enum: ['draft', 'active', 'archived']

Nested DTOs

Automatically generates schemas for nested DTO objects:

final readonly class AddressDto { public function __construct( #[Assert\NotBlank] public string $street, #[Assert\NotBlank] public string $city, public ?string $country = null, ) {} } final readonly class CreateUserRequest { public function __construct( public string $name, public AddressDto $address, // ← Nested DTO public ?AddressDto $billingAddress = null, // ← Nullable nested DTO ) {} }

Generated Schema:

CreateUserRequest: type: object required: ['name', 'address'] properties: name: type: string address: $ref: '#/components/schemas/AddressDto' billingAddress: $ref: '#/components/schemas/AddressDto' nullable: true AddressDto: type: object required: ['street', 'city'] properties: street: type: string city: type: string country: type: string nullable: true

Typed Collections

Supports typed arrays using PHPDoc annotations:

/**  * @param array<int, AddressDto> $addresses  * @param array<string> $tags  */ final readonly class CreateOrderRequest { public function __construct( public string $orderId, public array $addresses, public array $tags, ) {} }

Generated Schema:

CreateOrderRequest: type: object properties: orderId: type: string addresses: type: array items: $ref: '#/components/schemas/AddressDto' tags: type: array items: type: string

Union Types

Generates oneOf schemas for union types:

final readonly class FlexibleRequest { public function __construct( public string|int $identifier, // ← Union type ) {} }

Generated Schema:

FlexibleRequest: type: object properties: identifier: oneOf: - type: string - type: integer

🎯 Features

Route Detection

Scans your application's route configuration:

// config/autoload/routes.global.php return [ 'routes' => [ [ 'path' => '/api/v1/items', 'middleware' => [CreateItemHandler::class], 'allowed_methods' => ['POST'], ], ], ];

Automatic Operation Generation

Creates OpenAPI operations with:

  • HTTP method (GET, POST, PUT, DELETE, etc.)
  • Path parameters (extracted from {id} patterns)
  • Request body (for POST/PUT/PATCH)
  • Response schemas
  • Summary and operationId
  • Tags (from module namespace)

Path Parameters

Automatically detects and types path parameters:

'/api/v1/items/{id}' → parameter: id (format: uuid) '/api/v1/users/{userId}' → parameter: userId (type: integer)

📂 Generated Output

OpenAPI Structure

openapi: 3.0.0 info: title: My API version: 1.0.0 description: Automatically generated from routes and DTOs servers: - url: http://localhost:8080 description: Local development paths: /api/v1/items: post: operationId: createItem summary: create item tags: - Items requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateItemRequest' responses: 201: description: Success content: application/json: schema: $ref: '#/components/schemas/ItemResponse' 400: description: Bad Request 404: description: Not Found components: schemas: CreateItemRequest: # ... schema definition ItemResponse: # ... schema definition

🔧 Configuration

Full Configuration Example

// config/autoload/openapi.global.php return [ 'openapi' => [ 'title' => 'My API', 'version' => '1.0.0', 'description' => 'API for managing items', 'servers' => [ [ 'url' => 'https://api.example.com', 'description' => 'Production', ], [ 'url' => 'http://localhost:8080', 'description' => 'Development', ], ], ], ];

📊 Integration with Swagger UI

View your generated OpenAPI specification:

# Install Swagger UI composer require swagger-api/swagger-ui # Access at: http://localhost:8080/swagger-ui

Or use online tools:


🧪 Testing

# Run all tests composer test # Run with coverage composer test:coverage # Code style check composer cs-check # Fix code style composer cs-fix # Static analysis composer analyze # All quality checks composer quality

🤝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new features
  4. Ensure all quality checks pass (composer quality)
  5. Submit a pull request

📄 License

MIT License. See LICENSE for details.


🔗 Related Packages


🙏 Acknowledgments

Built with:


📞 Support


Made with ❤️ by Thorsten Merz

About

Automatic OpenAPI 3.0 specification generator from routes and DTOs. Extracts API documentation from code using PHP 8 attributes, Symfony Validator constraints, and PSR-15 middleware. JSON/YAML output, zero configuration. Framework-agnostic, CLI integration.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages