andrii-hrechyn/auto-documentation

Auto generated documentation for laravel

Installs: 44

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/andrii-hrechyn/auto-documentation

v2.0.0 2026-02-02 09:02 UTC

This package is auto-updated.

Last update: 2026-02-02 09:06:38 UTC


README

A fluent, object-oriented library for generating OpenAPI 3.1.0 documentation in Laravel applications.

PHP 8.3+ Laravel 7-11 License: MIT

Introduction

Auto Documentation lets you describe your API endpoints as PHP classes using a fluent builder API. The library auto-discovers your documentation classes, resolves reusable components via $ref, and generates a complete OpenAPI 3.1.0 specification as YAML — viewable through a built-in Redoc UI.

Key features:

  • Fluent PHP API — describe paths, schemas, parameters, and responses with method chaining
  • Auto-discovery — path and component classes are automatically found and registered
  • Reusable components — schemas, parameters, requests, and responses are deduplicated via $ref
  • Laravel integration — built-in artisan commands, route-based request body extraction, Sanctum auth support
  • OpenAPI 3.1.0 compliant output

Requirements

  • PHP 8.3+
  • Laravel 7, 8, 9, 10, or 11

Installation

Install via Composer:

composer require andrii-hrechyn/auto-documentation

Run the install command to scaffold the docs/ folder with examples and register the Docs\\ namespace in your composer.json autoload:

php artisan auto-doc:install

This creates the following structure:

docs/
├── Components/
│   ├── Parameters/
│   ├── Requests/
│   ├── Responses/
│   ├── Schemas/
│   └── Security/
├── Paths/
└── Documentation.php

Quick Start

1. Define your Documentation class

// docs/Documentation.php
namespace Docs;

use AutoDocumentation\BaseDocumentation;
use AutoDocumentation\Info;

class Documentation extends BaseDocumentation
{
    protected function info(): Info
    {
        return Info::make('My API', '1.0.0')
            ->description('API documentation');
    }
}

2. Create a path component

// docs/Paths/UsersPath.php
namespace Docs\Paths;

use AutoDocumentation\Base\PathComponent;
use AutoDocumentation\Paths\Method;
use AutoDocumentation\Paths\Path;
use AutoDocumentation\Properties\IntegerProperty;
use AutoDocumentation\Properties\StringProperty;

class UsersPath extends PathComponent
{
    public function path(): Path
    {
        return $this->make('users');
    }

    public function get(Method $method): Method
    {
        return $method
            ->operationId('listUsers')
            ->summary('List all users')
            ->tag('Users')
            ->jsonResponse([
                IntegerProperty::make('id')->example(1),
                StringProperty::make('name')->example('John'),
                StringProperty::make('email')->format('email'),
            ]);
    }
}

3. Generate documentation

php artisan auto-doc:generate

The specification is written to storage/app/auto-docs/documentation.yaml and served at /api/doc.

Documentation Class

The Documentation class extends BaseDocumentation and serves as the entry point for your API spec. It has one required method and several optional ones.

Info (required)

protected function info(): Info
{
    return Info::make('Blog Platform API', '2.0.0')
        ->description('API documentation for the Blog Platform')
        ->termsOfService('https://example.com/terms')
        ->contact(
            (new Contact())
                ->name('API Support')
                ->email('support@example.com')
                ->url('https://example.com/support')
        )
        ->license(
            License::make('MIT')
                ->url('https://opensource.org/licenses/MIT')
        );
}

Servers

protected function servers(): array
{
    return [
        Server::make('https://api.example.com/{version}')
            ->description('Production server')
            ->variable(
                Variable::make('version', 'v2')
                    ->enum(['v1', 'v2'])
                    ->description('API version')
            ),
    ];
}

Default Security

Set a global security scheme applied to all operations:

protected function defaultSecuritySchema(): ?SecurityRequirement
{
    return SanctumAuth::make();
}

Tags, Extensions & Tag Groups

Use additionalOptions() to define tags, vendor extensions, external docs, and tag groups:

public function additionalOptions(): void
{
    $this->openApi->externalDocs(
        ExternalDocs::make('https://example.com/docs')
            ->description('Full developer documentation')
    );

    $this->openApi->tag(
        (new Tag())->name('Users')->description('User management operations')
    );
    $this->openApi->tag(
        (new Tag())->name('Posts')->description('Blog post operations')
    );

    // Vendor extensions
    $this->openApi->extension('x-api-id', 'my-api');

    // Tag groups (Redoc x-tagGroups extension)
    $this->openApi->extension('x-tagGroups', [
        new Group('Content', ['Posts', 'Comments']),
        new Group('Access', ['Users', 'Auth']),
    ]);
}

Paths

PathComponent (recommended)

Path components are auto-discovered from the docs/Paths/ directory. Extend PathComponent and define HTTP methods as class methods:

class PostPath extends PathComponent
{
    public function path(): Path
    {
        return $this->make('posts/{postId}')
            ->parameter(
                Parameter::make('postId', ParameterIn::PATH)
                    ->description('The post ID')
                    ->required()
                    ->example(42)
            );
    }

    public function get(Method $method): Method
    {
        return $method
            ->operationId('getPost')
            ->summary('Get a post by ID')
            ->tag('Posts')
            ->response(
                SuccessfulResponse::make()->content([
                    ApplicationJson::make(PostSchema::make()),
                ])
            );
    }

    public function delete(Method $method): Method
    {
        return $method
            ->operationId('deletePost')
            ->summary('Delete a post')
            ->tag('Posts')
            ->response(NoContentResponse::make());
    }
}

Supported HTTP methods: get, post, put, patch, delete, head, options. Only define the methods your endpoint supports — the rest are omitted automatically.

AuthPathComponent

Extends PathComponent and automatically applies Sanctum security to all methods:

class AuthPath extends AuthPathComponent
{
    public function path(): Path
    {
        return $this->make('auth/login');
    }

    public function post(Method $method): Method
    {
        return $method
            ->operationId('login')
            ->summary('Authenticate and receive a token')
            ->tag('Auth')
            ->jsonRequest([
                StringProperty::make('email')->required()->format('email'),
                StringProperty::make('password')->required()->format('password'),
            ])
            ->jsonResponse([
                StringProperty::make('token')->example('1|abc123def456'),
                StringProperty::make('token_type')->default('Bearer'),
            ]);
    }
}

Route-based paths

Reference existing Laravel routes by name and extract request bodies from form request validation rules:

Route::make('posts.store', 'Create a new post')
    ->tag('Posts')
    ->requestBodyFromRequestClass()
    ->successfulResponse(PostSchema::make())
    ->secure();

Method options

Methods support the full OpenAPI operation spec:

$method
    ->operationId('updatePost')
    ->summary('Update a post')
    ->description('Full description here')
    ->tag('Posts')                                      // or ->tag((new Tag())->name('Posts'))
    ->deprecated()
    ->externalDocs(ExternalDocs::make('https://...'))
    ->extension('x-sunset', '2025-12-31')
    ->security(ApiKeyAuth::make())                      // per-operation security override
    ->request($request)
    ->response($response);

Properties

Properties describe individual fields within schemas and request/response bodies. All properties use make(string $name) and support method chaining.

Class Type Extra methods
StringProperty string minLength(), maxLength()
IntegerProperty integer minimum(), maximum()
NumberProperty number minimum(), maximum()
BooleanProperty boolean
ArrayProperty array minItems(), maxItems()
ObjectProperty object
DateTimeProperty string (format: date-time) minLength(), maxLength()
FileProperty string (format: binary) minLength(), maxLength()

Common methods available on all properties: required(), description(), example(), enum(), default(), format(), title(), extension().

// Examples
StringProperty::make('title')->required()->maxLength(255)->example('My Post'),
IntegerProperty::make('id')->example(42),
StringProperty::make('status')->enum(['draft', 'published', 'archived'])->default('draft'),
DateTimeProperty::make('created_at'),
ArrayProperty::make('tag_ids', IntegerSchema::make()),

Schemas

Schemas define the structure of data objects and are used inside properties, request bodies, and responses.

ObjectSchema

ObjectSchema::make([
    IntegerProperty::make('id')->example(1),
    StringProperty::make('name')->required(),
    StringProperty::make('email')->format('email'),
]);

ArraySchema

// Array of primitives
ArraySchema::make(IntegerSchema::make())->minItems(1);

// Array of objects
ArraySchema::make(
    ObjectSchema::make([
        StringProperty::make('title'),
    ])
);

Primitive Schemas

StringSchema, IntegerSchema, NumberSchema, BooleanSchema — used as items for ArraySchema or ArrayProperty.

Reusable Components

Components are self-registering classes that output $ref references in the generated spec. Extend the appropriate base class and implement the content() method.

SchemaComponent

class PostSchema extends SchemaComponent
{
    public function content(): ObjectSchema
    {
        return $this->schema([
            IntegerProperty::make('id')->example(42),
            StringProperty::make('title')->required()->maxLength(255)->example('My First Post'),
            StringProperty::make('body')->required(),
            StringProperty::make('status')->enum(['draft', 'published', 'archived'])->default('draft'),
            IntegerProperty::make('author_id')->example(1),
            ArrayProperty::make('comment_ids', IntegerSchema::make()),
            DateTimeProperty::make('published_at'),
            DateTimeProperty::make('created_at'),
        ])->extension('x-model', 'App\\Models\\Post');
    }
}

Usage: PostSchema::make() — returns a $ref to #/components/schemas/PostSchema.

ParameterComponent

class PageParameter extends ParameterComponent
{
    public function content(): Parameter
    {
        return $this->parameter('page', ParameterIn::QUERY)
            ->description('Page number for pagination')
            ->example(1);
    }
}

Usage: PageParameter::make() — returns a $ref to #/components/parameters/PageParameter.

RequestComponent

class CreatePostRequest extends RequestComponent
{
    public function content(): Request
    {
        return $this->request()
            ->required()
            ->description('Data for creating a new blog post')
            ->content([
                ApplicationJson::make(
                    ObjectSchema::make([
                        StringProperty::make('title')->required()->maxLength(255),
                        StringProperty::make('body')->required(),
                        StringProperty::make('status')->enum(['draft', 'published'])->default('draft'),
                    ])
                ),
            ]);
    }
}

ResponseComponent

class UnauthorizedResponse extends ResponseComponent
{
    public function content(): Response
    {
        return $this->response(401)
            ->description('Unauthenticated')
            ->content([
                ApplicationJson::make(ErrorSchema::make()),
            ]);
    }
}

Parameters

Parameters are created with a name and location (ParameterIn enum):

use AutoDocumentation\Enums\ParameterIn;

// Inline parameter
Parameter::make('postId', ParameterIn::PATH)
    ->description('The post ID')
    ->required()
    ->example(42);

// Query parameter
Parameter::make('search', ParameterIn::QUERY)
    ->description('Search term')
    ->example('laravel');

// Header parameter
Parameter::make('Accept-Language', ParameterIn::HEADER)
    ->description('Preferred language')
    ->example('en-US');

// Cookie parameter
Parameter::make('session', ParameterIn::COOKIE)
    ->description('Session identifier');

Attach parameters to a path:

$this->make('posts')
    ->parameter(PageParameter::make())
    ->parameter(PerPageParameter::make());

Request Bodies

JSON request (shorthand)

Use jsonRequest() on a method for a quick JSON body:

$method->jsonRequest([
    StringProperty::make('title')->required()->maxLength(255),
    StringProperty::make('body')->required(),
]);

Or pass a schema directly:

$method->jsonRequest(
    ObjectSchema::make([
        StringProperty::make('title')->required(),
    ])
);

Multipart/form-data

For file uploads, use MultipartFormData content type:

$method->request(
    Request::make()
        ->required()
        ->content([
            MultipartFormData::make(FileUploadSchema::make()),
        ])
);

From Laravel validation rules

When using Route::make(), extract the request body directly from a form request class:

Route::make('posts.store', 'Create a post')
    ->requestBodyFromRequestClass();

This inspects the controller method's type-hinted Request class and converts its rules() to an OpenAPI schema.

Responses

SuccessfulResponse

SuccessfulResponse::make()          // 200
SuccessfulResponse::make(201)       // 201
    ->description('Post created')
    ->content([
        ApplicationJson::make(PostSchema::make()),
    ]);

NoContentResponse

NoContentResponse::make();          // 204

JSON response (shorthand)

$method->jsonResponse([
    StringProperty::make('token')->example('abc123'),
    StringProperty::make('token_type')->default('Bearer'),
]);

Custom responses

Response::make(422)
    ->name('ValidationError')
    ->description('Validation failed')
    ->content([
        ApplicationJson::make(ErrorSchema::make()),
    ]);

Security

Built-in: SanctumAuth

use AutoDocumentation\Security\SanctumAuth;

// As global default
protected function defaultSecuritySchema(): ?SecurityRequirement
{
    return SanctumAuth::make();
}

// Per-operation
$method->security(SanctumAuth::make());

HTTP Security Scheme

HttpSecurityScheme::make('bearer')
    ->bearerFormat('JWT')
    ->description('JWT Bearer token');

API Key

use AutoDocumentation\Enums\ApiKeySecuritySchemeIn;

ApiKeySecurityScheme::make('X-API-Key', ApiKeySecuritySchemeIn::HEADER)
    ->description('API key passed in the X-API-Key header');

OpenID Connect

OpenIdConnectSecurityScheme::make('https://auth.example.com/.well-known/openid-configuration')
    ->description('OpenID Connect');

Custom security component

Create a reusable security requirement:

class ApiKeyAuth extends SecurityRequirement
{
    public function content(): SecurityScheme
    {
        return ApiKeySecurityScheme::make('X-API-Key', ApiKeySecuritySchemeIn::HEADER)
            ->description('API key passed in the X-API-Key header');
    }
}

Use it globally or per-operation:

// Global
protected function defaultSecuritySchema(): ?SecurityRequirement
{
    return ApiKeyAuth::make();
}

// Per-operation override
$method->security(ApiKeyAuth::make());

Configuration

Publish the config file with php artisan vendor:publish --tag=auto-documentation-config.

Option Default Description
generate_always false Auto-regenerate the spec on every page load (dev only)
environment ['local', 'development'] Environments where documentation routes are registered
routes.documentation api/doc URL path for the Redoc UI
routes.specification api/doc/spec URL path for the raw OpenAPI YAML
paths.source base_path('docs') Directory containing your documentation classes
paths.generated-doc storage_path('app/auto-docs') Directory where the generated YAML is stored

Environment variable AUTO_DOCUMENTATION_GENERATE_ALWAYS controls the generate_always option. AUTO_DOCUMENTATION_SOURCE controls the source docs path.

Generation

Artisan command

php artisan auto-doc:generate

Generates documentation.yaml from your Documentation class and all discovered path components.

Auto-regeneration

Set generate_always to true (or AUTO_DOCUMENTATION_GENERATE_ALWAYS=true in .env) to regenerate the spec on every documentation page load. Useful during development.

Routes

Route Description
/api/doc Redoc documentation UI
/api/doc/spec Raw OpenAPI YAML specification

Routes are only registered in the environments listed in the environment config option.

License

This library is licensed under the MIT License. See the LICENSE file for details.

Credits