cebe/php-openapi
Read and write OpenAPI 3.0.x YAML and JSON files as PHP objects, with a CLI tool for validating and converting descriptions. A low-level library used by higher-level API tooling.
paths, operations, components->schemas, and render docs, changelogs, or per-endpoint guides without hand-maintained duplication.validate (exit code 2 on errors) and convert, so "spec must be valid before merge" becomes a pipeline step, not a review convention. Cheap, high-leverage governance.hotmeteor/spectator and league/openapi-psr7-validator both build on this library — meaning we can validate real Laravel test requests/responses against the spec. This is the decision that most directly reduces integration defects.cebe/yii2-openapi is the reference implementation of that pattern; we'd port the idea, not the code.convert/inline (external-ref inlining into a single file) is the unglamorous but genuinely useful piece here.Adopt when:
$openapi->components->schemas['Foo']->properties['message'] works as expected.$ref and need resolution. The RESOLVE_MODE_INLINE vs RESOLVE_MODE_ALL distinction and recursive-reference handling are real engineering that we should not rebuild. Relative-path resolution was actively fixed through 1.8.0.Look elsewhere when:
webhooks, type arrays), this package does not get us there and the migration cost lands on us later. Decide this before adoption, not after.validate() is basic and incomplete, and Schema Object validation is unchecked. Full JSON-Schema validation exists only in the CLI. If validation depth is a requirement, we need a second tool in the pipeline.dedoc/scramble, darkaonline/l5-swagger, or vyuldashev/laravel-openapi instead, and use this only if we outgrow them.league/openapi-psr7-validator, not this package directly.Bottom line on fit: a strong enabler, weak product. Score it as infrastructure, budget for it accordingly, and isolate it behind a thin internal wrapper so a 3.1 migration or a package swap is a contained change.
To executives: This is a free, MIT-licensed PHP library that lets our code read and manipulate our API specification file directly. It is the cheapest possible way to unlock three things we currently do by hand: keeping documentation in sync with the API, automatically failing builds when the API contract breaks, and generating boilerplate code instead of writing it. Cost is a Composer dependency and a day of integration; the alternative is building and maintaining a parser ourselves. The risks are narrow and known: it supports OpenAPI 3.0 only (not 3.1), its built-in validation is shallow, and it is maintained by a very small team — so we adopt it for internal tooling and CI, and we don't put it on the request path.
To engineering: It's a well-factored low-level library, not a framework plugin. The object model maps one-to-one onto the OpenAPI 3.0 spec, so there's no abstraction to learn and no leaky query API to fight. Reference resolution — including external files, relative paths, and recursive pointers — is solved, and RESOLVE_MODE_INLINE lets us ship a single self-contained spec. It tracks modern PHP: releases target PHP 8.2/8.3, Symfony 7, and PHPStan 1.x, and 1.8.0 added getRawSpecData() for cases where we want the original document alongside the typed objects.
What we're explicitly accepting: 3.0.x only — treat any 3.1 requirement as a separate decision with its own cost. Validation is a structural smoke test, not a schema conformance check; if we need that, we pair it with a complementary validator and we don't pretend otherwise. Single-maintainer bus factor means we wrap it: one internal service class, no direct cebe\openapi\* imports scattered through the codebase, so replacement stays a contained refactor.
Recommendation: Adopt now, scoped to CI validation, spec-driven docs, and contract testing via spectator. Treat codegen and breaking-change detection as the next two increments once the spec is actually trustworthy. Revisit the 3.0-vs-3.1 question at the next planning cycle rather than deferring it indefinitely.
How can I help you explore Laravel packages today?