Download the PHP package langsys/openapi-docs-generator without Composer
On this page you can find all versions of the php package langsys/openapi-docs-generator. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download langsys/openapi-docs-generator
More information about langsys/openapi-docs-generator
Files in langsys/openapi-docs-generator
Package openapi-docs-generator
Short Description Automatic OpenAPI documentation generator from Spatie Laravel Data DTOs
License MIT
Informations about the package openapi-docs-generator
OpenAPI Docs Generator for Laravel
Generate OpenAPI 3.x documentation directly from Spatie Laravel Data DTOs. No intermediate annotation files, no UI bundling -- just your DTOs reflected into api-docs.json (and optionally YAML), merged with any hand-written controller annotations.
Table of Contents
- How It Works
- Requirements
- Installation
- Quick Start
- Attributes
- #[Example]
- #[Description]
- #[Omit]
- #[GroupedCollection]
- #[ItemType] / #[OneOfItemsFrom]
- Supported Property Types
- Enum Example
- Nested Data Classes
- DateTime / Carbon
- Optional Properties (
T|Optional)
- Collections
- Laravel Data v4 (Recommended)
- Laravel Data v3 (Legacy)
- Auto-Generated Response Schemas
- Example Generation (Faker)
- Artisan Commands
- Configuration Reference
- Multiple Documentation Sets
- Output Paths
- Security Definitions
- YAML Output
- Server / Base Path
- Constants
- Scan Options
- Thunder Client Integration
- Quick Start
- How It Works
- Auth Configuration
- Environment File
- Folder Grouping
- Request Bodies
- Merge Behavior
- Full Config Reference
- Viewing Your Docs
- Programmatic Usage
- Testing
- License
How It Works
DTO-generated schemas are additive: if a schema with the same name already exists from your annotations, the annotation version wins.
Requirements
- PHP 8.1+
- Laravel 10 / 11
- spatie/laravel-data ^3.9 or ^4.0
Installation
Publish the config file:
This creates config/openapi-docs.php.
Quick Start
-
Out of the box, the package scans your entire
app/directory for both controller annotations and Data subclasses. No path or namespace configuration needed — DTOs can live anywhere in your project. -
Create a Spatie Data class:
- Generate:
Output: storage/api-docs/api-docs.json with a UserData schema containing all properties, types, defaults, and auto-generated example values.
Attributes
Control how properties appear in the generated schema using PHP attributes on your DTO properties.
#[Example]
Set an explicit example value for a property.
Produces:
Faker function reference: prefix the example value with : to call a Faker method directly:
#[Description]
Add a description to a property.
#[Omit]
Exclude a property from the generated schema entirely.
#[GroupedCollection]
Mark a property as a grouped/dictionary structure. The argument is the key used in the example.
Simple grouped array (plain array type without a typed docblock):
Produces:
When combined with a typed collection (via @var docblock or #[DataCollectionOf]), it produces a dictionary-of-arrays structure instead. See Collections for details.
#[ItemType] / #[OneOfItemsFrom]
Declare a polymorphic array whose items can be one of several DTO variants — block-based content (Notion / Tiptap style), event envelopes, or any tagged-union payload.
#[ItemType('group', ?handle)]is applied to a Data class. It registers that class as a possible variant in a named group. The optionalhandledefaults to the snake-cased basename of the schema (withResource/Datasuffix stripped).#[OneOfItemsFrom('group')]is applied to an array property. The generator emits the property asarray<oneOf<...>>where eachoneOfmember is a generated wrapper schema named{Variant}Itemwith shape{ type: <handle>, data: <Variant> }.
For each variant, the generator emits a wrapper schema (ParagraphItem, ImageItem) that the property's oneOf references. Abstract Data subclasses are skipped from auto-schema generation, so a shared AbstractBlockResource base will not produce its own schema.
Supported Property Types
The generator handles these types automatically:
| PHP Type | OpenAPI Output |
|---|---|
string |
{ "type": "string" } |
int |
{ "type": "integer" } |
float |
{ "type": "number" } |
bool |
{ "type": "boolean" } |
array, Collection |
{ "type": "array", "items": { ... } } |
SomeData (nested Data class) |
{ "$ref": "#/components/schemas/SomeData" } |
SomeData[] via @var docblock (v4) |
{ "type": "array", "items": { "$ref": "..." } } |
Collection<int, SomeData> via @var docblock (v4) |
{ "type": "array", "items": { "$ref": "..." } } |
DataCollection with #[DataCollectionOf] (v3) |
{ "type": "array", "items": { "$ref": "..." } } |
BackedEnum |
{ "type": "string", "enum": ["case1", "case2"] } |
?BackedEnum (nullable enum) |
{ "type": "string", "enum": [...], "nullable": true } |
Carbon, DateTime, etc. |
{ "type": "string", "format": "date-time" } |
string\|Optional (Laravel Data) |
{ "type": "string" } — excluded from required |
Nullable (?string) |
Tracked as not required |
| Default values | Included as "default": value |
Enum Example
Produces:
If #[Example] is missing or its value isn't a valid enum case, a random case is picked automatically.
Nested Data Classes
Both AddressData and UserData schemas are generated. The address property uses $ref:
DateTime / Carbon
Properties typed as Carbon, CarbonImmutable, DateTime, DateTimeImmutable, or any DateTimeInterface implementation are automatically rendered as type: "string" with format: "date-time" — matching Laravel Data's default ISO 8601 serialization.
Produces:
Without this, Carbon and DateTime would be treated as nested objects with a $ref — which is incorrect since Laravel Data serializes them as ISO 8601 strings.
Optional Properties (T|Optional)
Spatie Laravel Data's Optional type is used in request DTOs to mark fields that can be omitted entirely from the payload (the "sometimes" validation rule). The generator strips Optional from union types and excludes the property from the schema's required array.
Produces a schema where only id is in the required array, and each optional property uses its underlying type:
Note:
Optionalis different from nullable (?string). Nullable means the field can be present with anullvalue.Optionalmeans the field can be absent from the request entirely. Both result in the property being excluded fromrequired, but they represent different semantics.
Collections
Laravel Data v4 (Recommended)
In Laravel Data v4, the recommended way to type collections is with @var docblock annotations on plain array or Collection properties. The generator parses these docblocks and produces typed array schemas automatically.
Array with ClassName[]:
Collection with generic syntax:
Both produce:
Grouped collection (v4 style):
Combine @var docblock with #[GroupedCollection] for dictionary-of-arrays output:
Produces:
Non-Data types like string[] or int[] in docblocks are ignored and fall through to plain array handling.
Laravel Data v3 (Legacy)
The v3 pattern using DataCollection with #[DataCollectionOf] is still fully supported:
Grouped collections with v3:
Both patterns produce identical OpenAPI output. If you're migrating from v3 to v4, you can update your DTOs incrementally -- existing DataCollection properties continue to work alongside new @var docblock properties.
Auto-Generated Response Schemas
Any DTO whose class name ends with Resource automatically gets three additional wrapper schemas:
| Class | Generated Schemas |
|---|---|
ProjectResource |
Project, ProjectResponse, ProjectPaginatedResponse, ProjectListResponse |
ProjectResponse: { status: bool, data: Project }
ProjectListResponse: { status: bool, data: [Project] }
ProjectPaginatedResponse: { status, page, records_per_page, page_count, total_records, data: [Project] }
The pagination wrapper fields are configured via dto.pagination_fields:
Example Generation (Faker)
When a property doesn't have an explicit #[Example] attribute, the generator produces example values automatically using Faker. It uses three resolution strategies in order:
1. Faker Attribute Mapper
Maps property name patterns to Faker methods. If a property name contains the pattern, the corresponding Faker method is called.
The matching is substring-based: a property named created_at matches _at and uses Faker::date().
2. Custom Functions
For cases where Faker doesn't have what you need, register custom functions:
The built-in CustomFunctions class provides:
id: returns a UUID for string types, a random integer for int typesdate: returns aY-m-d H:i:sformatted date string (or timestamp for int types)
To add your own, create a class and register it:
Custom functions receive the property type as their first argument.
3. Direct Faker Fallback
If no mapper pattern matches and no custom function exists, the property name itself is tried as a Faker method (converted to camelCase). So a property named first_name automatically calls Faker::firstName(). If that fails, it falls back to 0 for integers or an empty string for everything else.
Invoking Faker Directly from #[Example]
You can reference any Faker method from the #[Example] attribute by prefixing with ::
Artisan Commands
openapi:generate
Generate OpenAPI documentation from controller annotations and DTO schemas.
openapi:thunder
Generate a Thunder Client collection as a standalone command (requires api-docs.json to already exist).
See Thunder Client Integration for full details.
openapi:dto
Scaffold a Spatie Data class from an Eloquent model. Reads the database schema and generates typed properties.
Generates app/DataObjects/UserData.php:
On PHP 8.2+, properties are generated as readonly.
openapi:make-processor
Generate a swagger-php processor class. Processors let you customize how annotations are processed during scanning -- the most common use case is controlling the order tags appear in Swagger UI.
The command creates the file and prints the config snippet you need to add. See Scan Options / Processors for details.
Configuration Reference
All configuration lives in config/openapi-docs.php. The file has two main sections:
documentations-- per-documentation-set overrides (file names, scan paths)defaults-- shared settings inherited by all documentation sets
Every key under defaults can be overridden per documentation set via deep merge (associative arrays are merged recursively, scalars and indexed arrays are replaced).
Multiple Documentation Sets
Useful for API versioning or separating public/internal APIs. Each documentation set can override any value from defaults.
The annotations directories are scanned for both controller annotations and Data subclasses — one config, one scan.
Generate a specific set with php artisan openapi:generate v2, or all sets with --all.
Output Paths
The docs_json and docs_yaml filenames are set per documentation set (under documentations), not in defaults. They default to api-docs.json and api-docs.yaml.
Security Definitions
Inject OpenAPI security schemes and global security requirements into the generated api-docs.json. These define how your API authenticates and appear in the components/securitySchemes and top-level security sections of the spec.
Precedence: if you define a security scheme with the same name both in config and via a @OA\SecurityScheme annotation, the annotation version wins.
Note: these settings control what appears in your OpenAPI spec. They are separate from the Thunder Client auth config, which controls how Thunder Client requests are set up.
YAML Output
Generate a YAML copy alongside the JSON output:
Or via environment variable:
Server / Base Path
Add a server entry to the OpenAPI output. This tells API consumers (Swagger UI, Postman, etc.) the base URL for your API.
When set, the generated JSON includes:
When null, no servers section is added.
Constants
Define PHP constants that can be referenced inside @OA\* annotations. Useful for injecting environment-specific values into your documentation.
Use in annotations:
Scan Options
Controls how zircote/swagger-php scans your codebase for annotations.
exclude
Directories or files to skip when scanning for annotations. Paths are relative to the annotation directories.
open_api_spec_version
Which OpenAPI specification version to generate. Defaults to 3.0.0.
Processors
Processors are classes that run after swagger-php parses your annotations but before the final OpenAPI document is built. They let you modify, reorder, or enrich the parsed data.
The most common use case is controlling tag order in Swagger UI. By default, tags appear in whatever order swagger-php discovers them (which depends on file scan order). A processor lets you define an explicit order.
Generate a processor:
This creates app/Swagger/TagOrderProcessor.php:
Register it in config:
Custom processors are injected after swagger-php's BuildPaths processor, so all paths and operations are already resolved when your processor runs. You can pass either a class instance or a class name string.
Thunder Client Integration
Generate Thunder Client collections directly from your OpenAPI documentation. The generator reads your api-docs.json and creates a ready-to-use tc_col_{slug}.json file that Thunder Client auto-loads -- click "Send" immediately, no manual request setup needed.
Thunder Client Quick Start
-
Generate your OpenAPI docs first (if not already done):
-
Generate the Thunder Client collection:
- Open VS Code -- Thunder Client automatically detects files in
thunder-tests/and loads the collection.
The generator only creates requests for endpoints that exist in your api-docs.json. If a controller method doesn't have OpenAPI annotations, it won't appear in the collection.
How Thunder Client Generation Works
The generator reads the already-generated api-docs.json and:
- Creates a folder for each API tag (e.g. "Users", "Projects")
- Creates a request for each endpoint with the correct method, URL, headers, auth, and body
- Converts OpenAPI path parameters (
{id}) to Thunder Client variables ({{id}}) - Prefixes all URLs with a configurable base URL variable (
{{url}}/api/users) - Builds request bodies from schema examples for POST/PUT/PATCH endpoints
- Writes the collection to
thunder-tests/collections/tc_col_{slug}.json - Optionally generates an environment file with variables from
.env
Auth Configuration
The thunder_client.auth config maps your OpenAPI security scheme names to Thunder Client auth settings. Each key must match a scheme name used in your OpenAPI security annotations.
How scheme matching works:
- The generator reads each endpoint's
securityfield from the OpenAPI JSON (e.g."security": [{"bearerAuth": []}]) - It looks up each scheme name in
thunder_client.authto determine how to configure the Thunder Client request - If an endpoint references a scheme name that isn't in your config, it's skipped with a warning
- If an endpoint has no
securityfield,default_authis used
Multiple auth schemes on one endpoint:
If an endpoint supports multiple auth methods (e.g. both bearer and API key), the generator creates one request per scheme, with the scheme name appended to the request name:
If only one scheme is used, no suffix is added.
Environment File
Optionally generate a Thunder Client environment file (tc_env_{slug}.json) with variables pre-populated from your .env:
The environment file is only created once. If tc_env_local.json already exists, it is never overwritten -- you manage your own environment variables after initial creation.
Set 'environment' => null to skip environment generation entirely. You can always create environments manually in Thunder Client.
Folder Grouping
Requests are grouped into folders using the first tag from each endpoint's OpenAPI tags array:
Fallback when no tags: the generator infers a folder name from the URL path. It takes the first meaningful segment after skipping common prefixes:
| Path | Skip segments | Folder |
|---|---|---|
/api/users/{id} |
api |
Users |
/api/v1/projects |
api, v1 |
Projects |
/billing/invoices |
(none to skip) | Billing |
Configure which segments to skip:
Request Bodies
For POST, PUT, and PATCH endpoints, the generator builds a JSON request body from the schema defined in the endpoint's requestBody:
- Resolves
$refreferences to component schemas (up to 3 levels deep) - Uses
examplevalues from schema properties when available - Falls back to sensible defaults:
""for strings,0for integers,falsefor booleans,[]for arrays - Uses the first
enumvalue when a property has an enum constraint - Merges
allOfsub-schemas
The body is stored as a JSON string in the request, ready to edit and send.
Merge Behavior
The generator never overwrites existing requests. When you run it again after adding new endpoints:
- Existing requests, folders, and all their data are preserved untouched
- The collection
_idis reused (so Thunder Client treats it as the same collection) - Only new endpoints (by method + URL path) are appended
- New folders are created only if needed for new requests
This means you can safely customize requests in Thunder Client (add tests, change bodies, etc.) and re-run the generator without losing your changes.
Full Thunder Client Config
Viewing Your Docs
This package generates files only. To view them, use any OpenAPI-compatible viewer:
- Swagger UI (standalone or Docker)
- Scalar
- Redocly
- Stoplight Elements
- Import
api-docs.jsoninto Postman or Thunder Client
Programmatic Usage
Use the facade to generate docs from code:
Or resolve from the container:
For a specific documentation set:
Thunder Client generation programmatically:
Testing
License
MIT
All versions of openapi-docs-generator with dependencies
doctrine/annotations Version ^2.0
zircote/swagger-php Version ^4.0
spatie/laravel-data Version ^3.9|^4.0
symfony/yaml Version ^6.0|^7.0