methorz/openapi-generator

Automatic OpenAPI 3.0 specification generator from routes and DTOs

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/methorz/openapi-generator

dev-main 2025-12-01 09:32 UTC

This package is auto-updated.

Last update: 2025-12-01 09:32:25 UTC


README

Automatic OpenAPI 3.0 specification generator from routes and DTOs

CI codecov PHPStan 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

๐Ÿ“‹ Requirements

This package requires PHP 8.2+ and uses the following runtime dependencies:

Package Purpose Framework Required?
psr/container PSR-11 Container Interface โŒ No
symfony/console CLI command handling โŒ No (standalone utility)
symfony/yaml YAML file parsing/writing โŒ No (standalone utility)

Note: The Symfony packages used are standalone utility libraries, not framework components. They work independently without the Symfony framework and are used by many non-Symfony projects (Composer, PHPStan, PHPUnit, etc.).

๐Ÿ“ฆ 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

This package is part of the MethorZ HTTP middleware ecosystem:

Package Description
methorz/http-dto Automatic HTTP โ†” DTO conversion with validation
methorz/http-problem-details RFC 7807 error handling middleware
methorz/http-cache-middleware HTTP caching with ETag support
methorz/http-request-logger Structured logging with request tracking
methorz/openapi-generator Automatic OpenAPI spec generation (this package)

These packages work together seamlessly in PSR-15 applications.

๐Ÿ™ Acknowledgments

Built with:

๐Ÿ“ž Support

๐Ÿ”— Links

Made with โค๏ธ by Thorsten Merz