You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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)
spec pipeline (6.5), Builder as the shared entry point, three modes
a migration story for OpenApi\Attributes -> OpenApi\Spec worked out on a real project first, and whatever part of it turns out to be mechanical packaged as rector rules. Property is the awkward one: classic takes 61 constructor arguments because it extends Schema, spec takes 4 and holds a Schema, so that rewrite is a split rather than a rename
a reference migration of a real open-source project, published with its output diff
a seam to contribute pre-built attributes to a Specification before resolution - what framework integrations (routing, forms, serializer metadata) need to feed the pipeline without scanning
declare the attribute API frozen and drop the beta label in that minor
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 classicOpenApi\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.
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), theGenerator, processors. The spec pipeline is new in 6.5: a separate, much thinner set of attributes underOpenApi\Spec, collected into a flatSpecification, 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
@deprecatedmarker 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.
Contextgrew 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) andsetCompiler().What that buys:
$spec->add(new Spec\Info(...), new Spec\Schema(...))compiles straight to a PHP array. No moretoJson()+json_decode()to merge with something else. The classic annotation objects were never usable this way - every property is untyped and defaults to anUNDEFINEDsentinel, so reading one back means a sentinel check on every field.dateis not an OpenAPI type, and classic quietly rewritestype: 'date'totype: '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.isVersion()branches inside every attribute.ComponentIndex,Walker), and there is no_contextto fabricate.Version plan
v6 - now (6.10.0)
Builderas the shared entry point, three modes@deprecated, removed in 8.0, with a runtime deprecation when one is parsed (docs(Roadmap): say when classic goes, and mark what the file says is marked #2216) - the README had said so since 4.8, the code agrees nowGenerator::UNDEFINED/Generator::isDefault()re-targeted to 8.0 (docs(Roadmap): say when classic goes, and mark what the file says is marked #2216) - every classic custom processor uses them, so they go with classicOpenApi\Attributes->OpenApi\Specworked out on a real project first, and whatever part of it turns out to be mechanical packaged as rector rules.Propertyis the awkward one: classic takes 61 constructor arguments because it extendsSchema, spec takes 4 and holds aSchema, so that rewrite is a split rather than a renameSpecificationbefore resolution - what framework integrations (routing, forms, serializer metadata) need to feed the pipeline without scanningOnly the last item touches compatibility. Classic attributes, the
Generatorand 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
OpenApi\Attributeskeep working, output goes through the new pipelineMode::CLASSIC/--mode classicfor anyone who needs the oldGeneratorAPIBuilder::setMode()marked@deprecated, removed in 8.0LegacyTypeResolver, the relocation shims)OpenApi\Attributes(see below) - no surprisesv8 - classic removed
OpenApi\Annotations, docblock annotation support and theGeneratorare goneOpenApi\Attributes. "Spec" is really a mode name, and with one pipeline left it means nothing -OpenApi\Attributesis the better home. For code written againstOpenApi\Specthat is oneuseline per file (use OpenApi\Attributes as OA;where you haduse OpenApi\Spec as OA;), and a rector rule can do it - that hop really is a rename, the classes either side are the sameOpenApi\Attributesat that point: the class names stay but the constructors differ (classicPropertytakestype:, specPropertytakesschema:), 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\Attributesor annotations in your own code. Nothing to do in 6.x. If you are curious, run--mode hybrid(orBuilder::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
Compilerdo 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
OpenApi\Speckept as deprecated aliases in v8, so the namespace move is optional for one more major?