๐งช Processing Modes โ
Swagger-php supports three processing modes, which control how source code is turned into an OpenAPI document. Each uses a different internal pipeline.
Overview โ
| Classic | Hybrid | Spec | |
|---|---|---|---|
| Status | Stable | Beta | Beta |
| Attributes | OpenApi\Attributes | OpenApi\Attributes | OpenApi\Spec |
| Annotations | Yes | Yes | No |
| Pipeline | Generator โ Processors | Assembler โ Resolver โ HybridBridge โ Augmenters โ Compiler | Assembler โ Resolver โ Augmenters โ Compiler |
Classic (default) โ
Classic mode scans source files for OpenApi\Attributes (and legacy OpenApi\Annotations) and builds the OpenAPI document through the Generator and its processor chain.
use OpenApi\Builder;
$result = (new Builder())
->addSource('src/')
->build();
$result->toYaml();Classic mode gives access to the full Generator API through withGenerator(), including custom processors, analysers and configuration options.
Spec (beta) โ
Spec mode reimplements the pipeline from the ground up, using attributes from the OpenApi\Spec namespace. It introduces:
- Typed DTOs: attributes are simple data containers with constructor-promoted properties
- Slot-map nesting: explicit
merge()/contained()maps replace reflection-based nesting - Grouped augmenters: a three-phase pipeline (resolve โ reduce โ augment) with explicit ordering
- Version-aware compilers: separate compilers for OpenAPI 3.0, 3.1 and 3.2
use OpenApi\Builder;
use OpenApi\Builder\Mode;
$result = (new Builder())
->setMode(Mode::SPEC)
->addSource('src/')
->build();
$result->toYaml();Spec mode uses the OpenApi\Spec namespace (use OpenApi\Spec as OA;). See Using Spec Attributes for a full guide.
Beta
Spec mode is mostly feature-complete but still beta. The attribute API may evolve based on feedback before being promoted to default in a future major version.
Hybrid (beta) โ
Hybrid mode scans with the classic Generator, so existing OpenApi\Attributes work unchanged. It then bridges the result into the spec pipeline's augmenters and compilers.
This gives you the augmenter pipeline and version-aware compilation without rewriting any attribute code.
use OpenApi\Builder;
use OpenApi\Builder\Mode;
$result = (new Builder())
->setMode(Mode::HYBRID)
->addSource('src/')
->build();
$result->toYaml();Hybrid mode is the recommended transition path for existing projects that move to the new pipeline step by step.
Disclaimer
Hybrid mode will not work in heavily customized projects like NelmioApiDocBundle, or in projects adding custom processors.
Switching modes โ
CLI โ
./vendor/bin/openapi src/ --mode spec -o openapi.yaml
./vendor/bin/openapi src/ --mode hybrid -o openapi.yamlPHP โ
use OpenApi\Builder;
use OpenApi\Builder\Mode;
$builder->setMode(Mode::SPEC);
// or: $builder->setMode('spec');Behavioral differences โ
The modes aim for equivalent output from the same source, but differ in what they accept and in how they can be configured:
| Behavior | Classic | Hybrid | Spec |
|---|---|---|---|
Annotation support (/** @OA\... */) | Yes | Yes | No |
MergeJsonContent / MergeXmlContent | Yes | Yes | Yes (via OA\MediaType\Json) |
Processor chain (withGenerator()) | Yes | Scanning only (MergeJsonContent/MergeXmlContent) | No |
Resolver (withResolver()) | No | Yes (Resolver\Reflection by default) | Yes (Resolver\Reflection by default) |
Augmenter pipeline (withAugmenters()) | No | Yes | Yes |
Contributions (withSpecification()) | No | Yes | Yes |
| Version-aware compilation | No (single serializer) | Yes | Yes |
| Unreferenced components | Kept | Removed, with a notice | Removed, with a notice |
-c / -D keys | Processors, generator.* | Augmenters, generator.* | Augmenters |
Classic removes unreferenced components only when asked, with -c cleanUnusedComponents.enabled=true. Hybrid and spec remove them by default and log how many at notice level. -c cleanup.enabled=false keeps them, or in PHP:
use OpenApi\Augmenter;
use OpenApi\Utils\Pipeline;
$builder->withAugmenters(fn (Pipeline $pipeline) => $pipeline->get(Augmenter\Cleanup::class)->setEnabled(false));See Augmenters for the Cleanup options.
Migration path โ
The recommended migration path is:
Classic โ Hybrid: change to
setMode(Mode::HYBRID). No code changes are needed, and the augmenter pipeline becomes available. Output stays the same, with two exceptions:Components that no path references are removed, including a schema kept only for client code generation. Behavioral differences has the switch that keeps them.
-ctakes augmenter keys rather than processor keys, apart fromgenerator.*.--mode hybrid -D srclists them.
Hybrid โ Spec: when starting new code, use
OpenApi\Specattributes. ExistingOpenApi\Attributescode keeps working through hybrid mode. The spec attributes are not a one-for-one rename of the classic ones. A reusable attribute takes a singlecomponent:key, where classic spells the key after its own type (schema:,parameter:,request:,securityScheme:). See Components.Full Spec: once all code uses
OpenApi\Specattributes, switch tosetMode(Mode::SPEC).
Version timeline
- v6: spec and hybrid ship as opt-in beta. Classic remains the default.
- v7: hybrid becomes the default mode. Classic is still available.
setMode()and all classic code are deprecated. - v8: classic is removed, and so is
setMode(). Spec becomes the default. Spec attributes move toOpenApi\Attributes. For code already written againstOpenApi\Spec, that move is oneuseline per file. Coming from classic, the component keys are renamed as well.