PHPackages                             bambamboole/spectacular - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. bambamboole/spectacular

ActiveLibrary[API Development](/categories/api)

bambamboole/spectacular
=======================

OpenAPI and AsyncAPI tooling for Laravel applications.

0.11.0(2w ago)0428[2 PRs](https://github.com/bambamboole/spectacular/pulls)MITPHPPHP ^8.4CI passing

Since Jul 3Pushed 1mo agoCompare

[ Source](https://github.com/bambamboole/spectacular)[ Packagist](https://packagist.org/packages/bambamboole/spectacular)[ RSS](/packages/bambamboole-spectacular/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (21)Versions (24)Used By (0)

Spectacular
===========

[](#spectacular)

OpenAPI and AsyncAPI tooling for Laravel applications.

Spectacular gives you two things from the code you already write:

- **OpenAPI** — [Scramble](https://scramble.dedoc.co) extensions that document [spatie/laravel-query-builder](https://github.com/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](https://www.asyncapi.com)document, inferring channels and message payloads from the event class itself.

Requirements
------------

[](#requirements)

- PHP 8.4+
- Laravel 13+
- [`dedoc/scramble`](https://github.com/dedoc/scramble) `^0.13.30` (for the OpenAPI extensions)
- [`spatie/laravel-query-builder`](https://github.com/spatie/laravel-query-builder) `^7.0` (for the query-builder extension)

Installation
------------

[](#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
-------

[](#openapi)

Spectacular ships two Scramble [operation extensions](https://scramble.dedoc.co/usage/extending). 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

[](#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

[](#pagination-parameters)

`paginate()`, `simplePaginate()` and `cursorPaginate()` on a query-builder chain are documented automatically:

- `paginate` / `simplePaginate` → a `page` integer parameter (minimum `1`).
- `cursorPaginate` → a `cursor` string parameter.
- A `per_page`-style parameter is derived from a `$request->integer('per_page', 15)` (or `input`/`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

[](#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
--------

[](#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 invoking `broadcastOn()` 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()` `@return` PHPDoc (array shapes, `list`, `array`, nullable and union types are all understood). When `broadcastWith()` is absent, the event's public properties are used, mapping scalars, enums, `DateTimeInterface` and nested objects to JSON Schema.

### The `#[Message]` attribute

[](#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

[](#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

[](#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

[](#generating-the-document-1)

```
php artisan spectacular:asyncapi                  # print to stdout
php artisan spectacular:asyncapi --path=asyncapi.json
php artisan spectacular:asyncapi --pretty=false   # compact JSON
```

Testing
-------

[](#testing)

```
composer test      # Pest
composer check     # Pint (test), PHPStan, Pest — mirrors CI
```

The package is developed with [Orchestra Testbench](https://github.com/orchestral/testbench); the `workbench/` app provides the routes and events exercised by the test suite.

License
-------

[](#license)

Spectacular is open-sourced software licensed under the [MIT license](LICENSE.md).

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance94

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

12

Last Release

14d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/547137a6d80cad01ed1dd065b1c6af329d9a23a4134a895cff01e078cc155500?d=identicon)[bambamboole](/maintainers/bambamboole)

---

Top Contributors

[![bambamboole](https://avatars.githubusercontent.com/u/8823695?v=4)](https://github.com/bambamboole "bambamboole (39 commits)")

---

Tags

laravelopenapiscrambleasyncapispatie-query-builder

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/bambamboole-spectacular/health.svg)

```
[![Health](https://phpackages.com/badges/bambamboole-spectacular/health.svg)](https://phpackages.com/packages/bambamboole-spectacular)
```

###  Alternatives

[defstudio/telegraph

A laravel facade to interact with Telegram Bots

818355.4k3](/packages/defstudio-telegraph)[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.2k12.6M142](/packages/dedoc-scramble)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5226.7k](/packages/simplestats-io-laravel-client)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

46273.9k](/packages/harris21-laravel-fuse)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
