bambamboole/spectacular
Composer 安装命令:
composer require bambamboole/spectacular
包简介
OpenAPI and AsyncAPI tooling for Laravel applications.
README 文档
README
OpenAPI and AsyncAPI tooling for Laravel applications.
Spectacular gives you two things from the code you already write:
- OpenAPI — Scramble extensions that document spatie/laravel-query-builder filters, sorts, includes and sparse fieldsets, plus pagination parameters, directly from your controller actions — no annotations required.
- AsyncAPI — a generator that turns your Laravel broadcast events into an AsyncAPI 3.0 document, inferring channels and message payloads from the event class itself.
Requirements
- PHP 8.4+
- Laravel 13+
dedoc/scramble^0.13.30(for the OpenAPI extensions)spatie/laravel-query-builder^7.0(for the query-builder extension)
Installation
composer require bambamboole/spectacular
The service provider is auto-discovered. Publish the config file if you want to customise the defaults:
php artisan vendor:publish --tag=spectacular-config
This writes config/spectacular.php.
OpenAPI
Spectacular ships two Scramble operation extensions. They are registered
for you through config/spectacular.php:
'scramble' => [ 'extensions' => [ Bambamboole\Spectacular\OpenApi\Extensions\QueryBuilderExtension::class, Bambamboole\Spectacular\OpenApi\Extensions\PaginationExtension::class, ], ],
Query builder parameters
Any action that builds a Spatie\QueryBuilder\QueryBuilder chain is inspected statically, and the allowed operations
become documented query parameters:
use Spatie\QueryBuilder\AllowedFilter; use Spatie\QueryBuilder\QueryBuilder; class UsersController { public function __invoke(Request $request): AnonymousResourceCollection { $users = QueryBuilder::for(User::class) ->allowedFilters('name', AllowedFilter::exact('email')) ->allowedSorts('name', 'created_at') ->allowedIncludes('roles') ->allowedFields('id', 'name', 'email', 'roles.id', 'roles.name') ->paginate($request->integer('per_page', 15)); return UserResource::collection($users); } }
Produces filter[name], filter[email], sort, include, fields[users] and fields[roles] parameters — with
enums, descriptions and the correct array styling — plus page and per_page from the extension below.
Parameter names honour your config/query-builder.php settings (parameters.*, suffixes.*), so a customised
query-builder config is reflected in the generated document.
Pagination parameters
paginate(), simplePaginate() and cursorPaginate() on a query-builder chain are documented automatically:
paginate/simplePaginate→ apageinteger parameter (minimum1).cursorPaginate→ acursorstring parameter.- A
per_page-style parameter is derived from a$request->integer('per_page', 15)(orinput/query) argument, including its default.
Custom page/cursor names (pageName, cursorName) and the per-page key are read from the call arguments.
Generating the document
php artisan spectacular:openapi # print to stdout php artisan spectacular:openapi --path=openapi.json php artisan spectacular:openapi --pretty=false # compact JSON
The command renders the same document Scramble produces, so all of Scramble's own configuration applies.
AsyncAPI
Annotate the broadcast events you want documented with the #[Message] attribute. Spectacular scans the configured
paths for events implementing ShouldBroadcast / ShouldBroadcastNow that carry the attribute:
use Bambamboole\Spectacular\AsyncApi\Attributes\Message; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; #[Message( summary: 'User notification was created', description: 'Sent when a user receives a notification.', tags: ['notifications'], )] final class UserNotificationBroadcast implements ShouldBroadcast { public function __construct(public int $userId) {} public function broadcastOn(): array { return [new PrivateChannel('users.'.$this->userId)]; } public function broadcastAs(): string { return 'user.notification.created'; } /** * @return array{notificationId: int, team: string, sentAt: \Carbon\CarbonImmutable, status: BroadcastStatus} */ public function broadcastWith(): array { return [/* ... */]; } }
From an event, Spectacular derives:
- Channels — from the
#[Message(channels: [...])]argument, or inferred by invokingbroadcastOn()when the attribute omits them. Channel type (public,private,presence,private-encrypted) is detected from the name. - Message name — from
broadcastAs()when present, otherwise the fully-qualified class name. - Payload schema — from the
broadcastWith()@returnPHPDoc (array shapes,list<>,array<string, T>, nullable and union types are all understood). WhenbroadcastWith()is absent, the event's public properties are used, mapping scalars, enums,DateTimeInterfaceand nested objects to JSON Schema.
The #[Message] attribute
#[Message(
channels: [], // explicit channel names; inferred from broadcastOn() when empty
title: null, // human-friendly message title
summary: null, // short message summary
description: null, // longer description
tags: [], // AsyncAPI message tags
payload: null, // reference an external payload schema ($ref) instead of inferring
)]
Laravel extensions
By default the document includes x-laravel-* extension fields (channel type, source event class, whether it
broadcasts now). Disable them with laravel_extensions => false in the config.
Configuration
// config/spectacular.php 'asyncapi' => [ 'version' => '3.0.0', 'default_content_type' => 'application/json', 'info' => [ 'title' => env('APP_NAME', 'Laravel').' AsyncAPI', 'version' => env('APP_VERSION', '0.0.1'), ], 'laravel_extensions' => true, 'scan_paths' => [ app_path('Events'), ], ],
Generating the document
php artisan spectacular:asyncapi # print to stdout php artisan spectacular:asyncapi --path=asyncapi.json php artisan spectacular:asyncapi --pretty=false # compact JSON
Testing
composer test # Pest composer check # Pint (test), PHPStan, Pest — mirrors CI
The package is developed with Orchestra Testbench; the workbench/ app
provides the routes and events exercised by the test suite.
License
Spectacular is open-sourced software licensed under the MIT license.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-03