Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Openapi Laravel Package

php-openapi/openapi

PHP library for reading, validating, and writing OpenAPI 3.0 specifications. Parse JSON or YAML into an object model, resolve references, inspect paths and schemas, and generate updated spec files—useful for API tooling, docs, and governance.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the parser:

composer require php-openapi/openapi

For YAML specs you also need symfony/yaml (JSON specs have no extra dependency). Laravel already ships with it in many projects.

The single entry point you'll use 90% of the time is OpenApi\Reader:

use OpenApi\Reader;

$spec = Reader::readFromYamlFile(base_path('openapi.yaml'));
// also: readFromJsonFile(), readFromYaml(), readFromJson()

if (! $spec->validate()) {
    foreach ($spec->getErrors() as $error) {
        $this->error($error);
    }
    return 1;
}

Where to look first:

  • OpenApi\Reader — the factory methods for loading a spec from a file, string, URL.
  • $spec->paths, $spec->components->schemas, $spec->info — the object graph you'll navigate.
  • $spec->validate() + $spec->getErrors() — the built-in structural validator.
  • $spec->resolveReferences() — resolves every $ref into the real object instance.

First use case: a php artisan openapi:lint command that parses the spec and fails CI when validation errors exist. This is the fastest way to prove the package works in your app before you build anything more sophisticated on top of it.

class LintOpenApiCommand extends Command
{
    protected $signature = 'openapi:lint {file=openapi.yaml}';

    public function handle()
    {
        try {
            $spec = Reader::readFromYamlFile(base_path($this->argument('file')));
        } catch (\Throwable $e) {
            $this->error("Could not parse spec: {$e->getMessage()}");
            return self::FAILURE;
        }

        if ($spec->validate()) {
            $this->info('Spec is valid.');
            return self::SUCCESS;
        }

        foreach ($spec->getErrors() as $error) {
            $this->error($error);
        }
        return self::FAILURE;
    }
}

Implementation Patterns

Bind the parsed spec as a singleton. Parsing and validation are not free — do it once per request lifecycle and reuse it via the container.

// AppServiceProvider::register()
$this->app->singleton(OpenApi::class, function () {
    $spec = Reader::readFromYamlFile(base_path('openapi.yaml'));
    $spec->resolveReferences();
    return $spec;
});

After resolveReferences() the object graph is fully walkable — $spec->paths['/users']->get->responses['200']->content['application/json']->schema returns the concrete Schema, not a Reference.

Walk operations to generate route stubs, docs, or Postman collections. The verbs are individual nullable properties on each PathItem:

$verbs = ['get','post','put','patch','delete','head','options','trace'];

foreach ($spec->paths as $path => $pathItem) {
    foreach ($verbs as $verb) {
        $operation = $pathItem->{$verb};
        if ($operation === null) {
            continue;
        }

        $operationId = $operation->operationId ?? "{$verb} {$path}";
        // $operation->parameters, $operation->requestBody, $operation->responses
    }
}

Extract a JSON Schema from a component. Useful for emitting TypeScript interfaces or validating payloads client-side:

$schema = $spec->components->schemas['User'];
$jsonSchema = json_encode($schema); // round-trips to a plain JSON Schema doc

Use it as the parser behind request/response contract tests. php-openapi deliberately does not validate HTTP messages. Pair it with league/openapi-psr7-validator and convert the Laravel request to PSR-7 first:

use League\OpenAPIValidation\PSR7\ValidatorBuilder;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;

$validator = (new ValidatorBuilder)->fromYamlFile(base_path('openapi.yaml'))->getRequestValidator();
$psrRequest = app(PsrHttpFactory::class)->createRequest(request());
$validator->validate($psrRequest);

Detect breaking changes between two spec revisions. Parse both, walk components->schemas and paths, and diff the operation/response key sets. $spec->info->version gives you the spec's own semantic version for tagging. This is a cheap alternative to heavier schema-diffing tools when you only care about "did we remove an endpoint or required field?"

Generate a TypeScript client-side API surface by iterating components->schemas, mapping Schema::$type (string, integer, object, array) plus $schema->required to a .d.ts file. Because everything is a plain PHP object, this is trivial templating.

Gotchas and Tips

  • validate() returns a bool, it never throws. The failure mode is silent — you must call getErrors() to see what's wrong. A valid-looking spec can still be flagged for things like missing info or malformed $ref targets.
  • resolveReferences() is explicit, not automatic. Without it, traversing into a components/schemas/* entry gives you a Reference wrapper object, not the real Schema. Any code that reflects on $schema->type or $schema->properties will silently get null until you resolve.
  • Circular $refs will blow up resolution. If you have self-referencing schemas (tree nodes, linked lists), call resolveReferences() with the recursion flag off ($recursive = false) or pass a resolutionCallback that keeps them lazy for the parts of the tree you don't need.
  • External file references need a base path. $ref: './common.yaml#/components/schemas/Error' resolves relative to the original file's directory. When reading a spec from a string or a stream, supply a ReferenceContext pointing at the right base path, or the resolution fails with an unresolvable-reference exception.
  • Reader methods throw on malformed input. Wrap readFromYamlFile / readFromJsonFile in try/catch — a syntax error in YAML will throw before you ever reach validate().
  • OpenAPI 3.1 support is version-sensitive. Confirm the exact version you've installed if you depend on 3.1 features (nullable-as-type-arrays, $schema, webhooks). Pin the package and add a test around the features you actually rely on.
  • The package is a parser, not a server. It ships no middleware, no route binding, no validation of live requests. That's a deliberate boundary — pick league/openapi-psr7-validator for runtime checks and use this for everything static.
  • Cache the parsed spec aggressively in production. Parsing plus resolveReferences() on a large spec is expensive. If you generate docs or types at build time, do it in a deploy step to a JSON artifact rather than at request time.
  • $spec->info, $spec->paths, etc. are typed objects, not arrays. They implement ArrayAccess and Countable, so foreach and isset work naturally, but array_map does not — use iterator_to_array() if you need to pass to array-expecting code.
  • Schema round-tripping is your extension point. Because Schema implements JsonSerializable, json_encode($schema) is the cleanest way to bridge into any other JSON-Schema-aware library — the output is standard draft-04-compatible JSON Schema and most tools will accept it without massaging.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console