Skip to content

Roadmap: the spec pipeline, v6 → v7 → v8 #1953

Description

@DerManoMann

Pinned. This body is the current plan and gets updated as things ship; the comments below are the history of how it got here.

swagger-php 6 has two ways of turning PHP into an OpenAPI document. The classic pipeline is what everybody uses today: OpenApi\Attributes (or docblock annotations), the Generator, processors. The spec pipeline is new in 6.5: a separate, much thinner set of attributes under OpenApi\Spec, collected into a flat Specification, enriched by augmenters and compiled per OpenAPI version (3.0, 3.1, 3.2). In between sits hybrid mode - it scans your existing classic attributes and runs the result through the new pipeline. All three are described at Processing modes.

This is the plan for getting from the first to the second over three majors. The plan itself lives in ROADMAP.md; this issue is the discussion and the tick list. Nothing breaks in 6.x - everything new is opt-in, and a @deprecated marker names the version that removes the thing, so anything marked for 8.0 keeps working through v7 unchanged.

The problem:
The classic attributes do way too much - capture data, validate, nest, merge, serialize and branch on the OpenAPI version. Context grew to share state across all of that. Adding a field, supporting a new spec version or extending the library from the outside is all harder than it should be.

The idea:
Attributes are plain typed constructors and nothing else. Validation, type resolution, version handling etc. happen in stages you can hook into: Builder::withAugmenters(), withResolver(), withAttributeFactory() (which is where attribute translators are registered) and setCompiler().

What that buys:

  • Programmatic use, without scanning. Spec attributes are ordinary value objects with typed properties: $spec->add(new Spec\Info(...), new Spec\Schema(...)) compiles straight to a PHP array. No more toJson() + json_decode() to merge with something else. The classic annotation objects were never usable this way - every property is untyped and defaults to an UNDEFINED sentinel, so reading one back means a sentinel check on every field.
  • Mistakes reported instead of absorbed. date is not an OpenAPI type, and classic quietly rewrites type: 'date' to type: 'string', format: 'date' - so the attribute stays wrong and the next person copies it. The new pipeline says Schema has unknown type "date" instead. Running hybrid over a real codebase turned up three of them.
  • OpenAPI 3.1 by default, with 3.0 and 3.2 as compiler targets instead of isVersion() branches inside every attribute.
  • Less for integrations to reinvent. Component lookup and traversal are library API (ComponentIndex, Walker), and there is no _context to fabricate.

Version plan

v6 - now (6.10.0)

Only the last item touches compatibility. Classic attributes, the Generator and the processors are deliberately not marked in v6 - a stable API does not get deprecated in favour of one still labelled beta.

v7 - hybrid by default, classic deprecated

  • hybrid becomes the default mode: existing OpenApi\Attributes keep working, output goes through the new pipeline
  • classic stays available via Mode::CLASSIC / --mode classic for anyone who needs the old Generator API
  • all classic code - annotations, attributes, the related pipeline code - plus the bridge and Builder::setMode() marked @deprecated, removed in 8.0
  • everything whose marker says 7.0 is removed (LegacyTypeResolver, the relocation shims)
  • the v7 migration guide says, with the version, that v8 moves the spec attributes to OpenApi\Attributes (see below) - no surprises

v8 - classic removed

  • classic pipeline, OpenApi\Annotations, docblock annotation support and the Generator are gone
  • the spec attributes move to OpenApi\Attributes. "Spec" is really a mode name, and with one pipeline left it means nothing - OpenApi\Attributes is the better home. For code written against OpenApi\Spec that is one use line per file (use OpenApi\Attributes as OA; where you had use OpenApi\Spec as OA;), and a rector rule can do it - that hop really is a rename, the classes either side are the same
  • if you are still on the classic OpenApi\Attributes at that point: the class names stay but the constructors differ (classic Property takes type:, spec Property takes schema:), so you get unknown-named-parameter errors at generation time rather than missing classes. The v8 migration guide will lead with that; the rector set is the fix

(My July notes below had the namespace move as v9, optional icing. It is v8 now, because there is no reason to make people wait a major for the better name.)

What this means for you

You use OpenApi\Attributes or annotations in your own code. Nothing to do in 6.x. If you are curious, run --mode hybrid (or Builder::setMode(Mode::HYBRID)) over your codebase - the output should be the same, and any warnings it prints are real. When you want the new attributes, the rector set is a 6.x item above; until then the spec attributes guide has the differences.

You maintain a package wrapping swagger-php (a bundle, a framework integration). Hybrid is your compatibility path. The pre-resolve contribution seam above is what lets non-attribute metadata into the pipeline, and it is the item where I would most like to hear what you need. The hooks that exist today are at Extension points.

You build documents in code and never scan. Spec attributes as value objects plus the Compiler do that today; the docs for it are on the list.

You want the smallest possible migration. Stay on classic through v7. The rector set exists before v8 does.

Still to decide

  • Default output version at v7. Hybrid defaults to OpenAPI 3.1.0 today, classic to 3.0.0. Flipping the default mode flips the default version for everyone unless v7 keeps 3.0.0 as the default. If your consumer is 3.0-only, say so here.
  • OpenApi\Spec kept as deprecated aliases in v8, so the namespace move is optional for one more major?
  • Anything else you would need before moving a real project - comments welcome.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions