jurager / documentator
OpenAPI specification generator for Laravel
Installs: 83
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/jurager/documentator
Requires
- php: ^8.2
- fakerphp/faker: ^1.23
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.25
README
Generate OpenAPI from Laravel routes with automatic schema extraction from Form Requests, validation rules, and API Resources.
Note
The documentation for this package is currently being written. For now, please refer to this readme for information on the functionality and usage of the package.
- Features
- Requirements
- Quick Start
- Usage
- Configuration
- How Schema Detection Works
- PHPDoc Annotations
- Custom Response Format
- Validation Rules Mapping
- Troubleshooting
- License
Features
- Automatic OpenAPI generation from Laravel routes
- Schema detection from FormRequest, inline validation, and API Resources
- Built-in formats: REST (
simple) and JSON:API (json-api) - PHPDoc-driven docs:
@summary,@group,@response, etc. - Built-in security schemes support (Bearer, API key, OAuth2, OpenID)
- Example payload generation via FakerPHP
- Configurable output and route filtering
Requirements
- PHP 8.1+
- Laravel 10.x or 11.x
Quick Start
Install the package:
composer require jurager/documentator
Publish config:
php artisan vendor:publish --tag=documentator-config
Include your API routes in config/documentator.php:
'routes' => [ 'include' => ['api/*'], ],
Generate spec:
php artisan docs:generate
Open result file:
docs/openapi.json
Import it into Swagger UI, Postman, Insomnia, or any OpenAPI-compatible tool.
Usage
Basic command:
php artisan docs:generate
Options:
# Override output path php artisan docs:generate --output=public/api.json # Override response envelope format (simple | json-api | custom) php artisan docs:generate --format=json-api
Configuration
Main config file: config/documentator.php
1) API metadata and output
'openapi_version' => '3.0.3', 'info' => [ 'title' => env('OPENAPI_TITLE', 'API Documentation'), 'version' => env('OPENAPI_VERSION', '1.0.0'), 'description' => env('OPENAPI_DESCRIPTION'), ], 'output' => [ 'path' => env('OPENAPI_OUTPUT', 'docs/openapi.json'), 'format' => env('OPENAPI_OUTPUT_FORMAT', 'json'), // json | yaml 'pretty_print' => env('OPENAPI_PRETTY_PRINT', true), ],
2) Servers
'servers' => [ [ 'url' => env('APP_URL', 'http://localhost'), 'description' => 'Development server', ], [ 'url' => 'https://api.example.com', 'description' => 'Production server', ], ],
3) Security
'security' => [ 'schemes' => [ 'bearerAuth' => [ 'type' => 'http', 'scheme' => 'bearer', 'bearerFormat' => 'JWT', ], ], 'default' => ['bearerAuth'], // applied to all endpoints ],
4) Route discovery
'routes' => [ 'include' => ['api/*'], 'exclude' => ['sanctum/*', 'horizon/*', 'telescope/*', '_ignition/*'], 'exclude_middleware' => ['web'], 'methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], ],
5) Response format
'format' => env('OPENAPI_FORMAT', 'simple'), // simple | json-api 'custom_formats' => [ 'hal' => App\OpenApi\Formats\HalFormat::class, ],
6) Resources and examples
'resources' => [ 'namespaces' => [ 'App\\Http\\Resources', 'App\\Models', ], 'suffix' => 'Resource', ], 'examples' => [ 'enabled' => true, 'locale' => env('FAKER_LOCALE', 'en_US'), 'seed' => null, 'collection_size' => 2, ],
7) Tags and default responses
'tags' => [ 'auto_generate' => true, 'definitions' => [ 'Users' => 'User management and profiles', 'Auth' => 'Authentication endpoints', ], 'sort' => true, ], 'responses' => [ 'default' => [ '401' => ['$ref' => '#/components/responses/Unauthorized'], '403' => ['$ref' => '#/components/responses/Forbidden'], ], ],
8) Advanced options
'advanced' => [ 'cache_parsed_files' => true, 'include_deprecated' => false, 'validate_schemas' => env('OPENAPI_VALIDATE', true), 'deep_scan_controllers' => true, ],
How Schema Detection Works
Documentator builds request/response schemas from:
- FormRequest
rules() - Inline validation (
$request->validate([...])) - Controller validation (
validate(...)) - API Resources (
JsonResource)
Example:
class UserResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'created_at' => $this->created_at, ]; } }
PHPDoc Annotations
Example:
/** * Get users * * @group Users * @queryParam page integer Page number * @queryParam per_page integer Items per page * @response 200 {"data": [{"id": 1, "name": "John"}]} */ public function index() { }
Supported annotations:
| Annotation | Purpose |
|---|---|
@summary text |
Short endpoint summary |
@description text |
Detailed endpoint description |
@group Name |
Tag/group name |
@resource name |
Override detected resource name |
@queryParam name type [required] desc |
Query parameter |
@bodyParam name type [required] desc |
Body parameter |
@urlParam name type [required] desc |
URL/path parameter |
@response status {"json"} |
Response example |
@deprecated |
Mark endpoint as deprecated |
@authenticated |
Requires authentication |
@unauthenticated |
Public endpoint |
Custom Response Format
Create a class extending Jurager\Documentator\Formats\AbstractFormat:
namespace App\Documentator; use Jurager\Documentator\Formats\AbstractFormat; class TelegramFormat extends AbstractFormat { public function name(): string { return 'telegram'; } public function description(): string { return 'Telegram Bot API style responses'; } protected function successSchema(): string { return 'TelegramSuccess'; } protected function errorSchema(): string { return 'TelegramError'; } public function schemas(): array { return [ 'TelegramSuccess' => [ 'type' => 'object', 'required' => ['ok', 'result'], 'properties' => [ 'ok' => ['type' => 'boolean', 'example' => true], 'result' => ['type' => 'object'], ], ], 'TelegramError' => [ 'type' => 'object', 'required' => ['ok', 'error_code', 'description'], 'properties' => [ 'ok' => ['type' => 'boolean', 'example' => false], 'error_code' => ['type' => 'integer'], 'description' => ['type' => 'string'], ], ], ]; } }
Register it in config:
'custom_formats' => [ 'telegram' => App\Documentator\TelegramFormat::class, ], 'format' => 'telegram',
Validation Rules Mapping
| Laravel Rule | OpenAPI |
|---|---|
integer, int, numeric |
type: integer |
boolean, bool |
type: boolean |
string |
type: string |
email |
type: string, format: email |
url |
type: string, format: uri |
uuid |
type: string, format: uuid |
date |
type: string, format: date |
datetime |
type: string, format: date-time |
array |
type: array |
json |
type: object |
file, image |
type: string, format: binary |
min:N |
minLength or minimum |
max:N |
maxLength or maximum |
in:a,b,c |
enum: [a, b, c] |
required |
required field |
nullable |
nullable field |
Troubleshooting
No routes found
If generator says no routes were found:
- Verify
routes.includeinconfig/documentator.php. - Check routes are registered:
php artisan route:list. - Ensure route patterns are not excluded by
routes.exclude. - Verify methods are allowed in
routes.methods.
Empty paths in generated spec
- Ensure controller classes and methods exist.
- Avoid closure routes for endpoints you want documented.
- Check controller loading errors in your app.
Custom format not found
- Register class in
custom_formats(notformats). - Ensure class extends
AbstractFormat. - Verify namespace/class name is correct.
Resource class not detected
- Add namespace to
resources.namespaces. - Ensure class extends
JsonResource. - Check class suffix matches
resources.suffix.
License
This package is open-sourced software licensed under the MIT license.