Skip to content

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 ​

ClassicHybridSpec
StatusDeprecatedDefault, deprecatedStable
AttributesOpenApi\AttributesOpenApi\Attributes, OpenApi\SpecOpenApi\Spec
Docblock annotationsYesYesNo
PipelineGenerator → ProcessorsAssembler → Resolver → HybridBridge → Augmenters → CompilerAssembler → Resolver → Augmenters → Compiler

Classic ​

Classic mode scans source files for classic attributes (OpenApi\Attributes) and docblock annotations (OpenApi\Annotations) and builds the OpenAPI document through the Generator and its processor chain.

php
use OpenApi\Builder;
use OpenApi\Builder\Mode;

$result = (new Builder())
    ->setMode(Mode::CLASSIC)
    ->addSource('src/')
    ->build();

$result->toYaml();

Classic mode gives access to the full Generator API through withGenerator(), including custom processors, analysers and configuration options.

Spec ​

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
php
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.

Hybrid ​

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. OpenApi\Spec attributes are built as in spec mode, so both can be mixed.

This gives you the augmenter pipeline and version-aware compilation without rewriting any attribute code.

php
use OpenApi\Builder;

$result = (new Builder())
    ->addSource('src/')
    ->build();

$result->toYaml();

Custom processors

Custom processors run in hybrid mode only over the annotation instances as scanned. A project that depends on them stays on classic until they are rewritten as augmenters, see Migrating to v7.

Switching modes ​

CLI ​

shell
./vendor/bin/openapi src/ --mode classic -o openapi.yaml
./vendor/bin/openapi src/ --mode spec -o openapi.yaml

PHP ​

php
use OpenApi\Builder;
use OpenApi\Builder\Mode;

$builder->setMode(Mode::CLASSIC);
// or: $builder->setMode('classic');

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:

BehaviorClassicHybridSpec
Docblock annotations (/** @OA\... */)YesYesNo
MergeJsonContent / MergeXmlContentYesYesYes (via OA\MediaType\Json)
Processor chain (withGenerator())YesScanning only (MergeJsonContent/MergeXmlContent)No
Resolver (withResolver())NoYes (Resolver\Reflection by default)Yes (Resolver\Reflection by default)
Augmenter pipeline (withAugmenters())NoYesYes
Contributions (withSpecification())NoYesYes
Version-aware compilationNo (single serializer)YesYes
Unreferenced componentsKeptRemoved, with a noticeRemoved, with a notice
-c / -D keysProcessors, 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:

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:

  1. Classic → Hybrid: hybrid is the default, so this needs no code changes, and the augmenter pipeline becomes available. Output stays the same, with the exceptions listed in Migrating to v7.

  2. Hybrid → Spec: when starting new code, use OpenApi\Spec attributes. Existing OpenApi\Attributes code keeps working through hybrid mode. The spec attributes are not a one-for-one rename of the classic ones. A reusable attribute takes a single component: name, where classic spells the name field after its own type (schema:, parameter:, request:, securityScheme:). See Components.

  3. Full Spec: once all code uses OpenApi\Spec attributes, the migration is done. Hybrid builds them as spec mode does, so no mode switch is needed.

Version timeline

  • v6: spec and hybrid ship as opt-in beta. The spec attribute API is frozen within v6, and Builder is the stable entry point for every mode. Classic remains the default.
  • v7: hybrid becomes the default mode, and spec and hybrid are no longer beta. 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 to OpenApi\Attributes. For code already written against OpenApi\Spec, that move is one use line per file. Coming from classic, the component name fields are renamed as well.