Back to Swagger Php

Using the `Builder`

docs/reference/builder.md

6.5.16.3 KB
Original Source

Using the Builder

Introduction

The Builder class is the recommended entry point for generating OpenAPI documents from PHP code. It provides a clean, fluent API and returns a Result object with access to the generated spec, scanned files, and validation diagnostics.

Basic usage

php
$result = (new \OpenApi\Builder())
    ->addSource('src/Controllers')
    ->addSource('src/Models')
    ->build();

echo $result->toYaml();

Processing modes

The Builder supports three processing modes via setMode(string|Mode $mode):

Classic (default)

Scans source files for annotations/attributes and assembles the OpenAPI document via the Generator pipeline. This is the stable, production-ready mode.

php
use OpenApi\Builder\Mode;

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

Spec (beta) {#mode-spec}

Runs the new spec attributes pipeline end-to-end: Assembler → Augmenters → Compiler. Uses pure PHP 8.1+ attributes from the OpenApi\Spec namespace with typed DTOs and version-aware compilers.

php
$builder->setMode(Mode::SPEC);
// or: $builder->setMode('spec');

Hybrid (beta) {#mode-hybrid}

Uses the classic Generator for scanning, then bridges the result into the spec pipeline's augmenters and compilers. A transition path for existing projects that want access to the new augmenter pipeline without rewriting all annotations.

php
$builder->setMode(Mode::HYBRID);
// or: $builder->setMode('hybrid');

::: tip Choosing a mode See the Processing Modes guide for a full comparison and migration path. :::

API

Sources

php
// Add sources one at a time
$builder->addSource('src/Controllers');
$builder->addSource(new \OpenApi\Utils\SourceFinder('src/', ['tests']));

// Or set all at once
$builder->setSources(['src/Controllers', 'src/Models']);

Sources can be directory paths, file paths, \SplFileInfo, \Symfony\Component\Finder\Finder instances, or nested iterables of these.

Reflector sources (spec/hybrid mode)

In spec and hybrid mode, you can pass \Reflector instances (e.g. \ReflectionClass) directly instead of file paths. This is useful when you already have reflection objects available or want to build a spec from a specific set of classes without file scanning:

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

$result = (new Builder())
    ->setMode(Mode::SPEC)
    ->addSource([
        new \ReflectionClass(App\Controllers\PetController::class),
        new \ReflectionClass(App\Models\Pet::class),
    ])
    ->build();

::: warning Reflector sources are not supported in classic mode — they require the spec or hybrid pipeline. :::

Version

php
$builder->setVersion('3.1.0');

Sets the target OpenAPI version. Version resolution order:

  1. Explicit setVersion() call (highest priority)
  2. Version declared in the source #[OA\OpenApi(version: '...')] attribute
  3. Falls back to 3.0.0 (classic) or 3.1.0 (spec/hybrid)

Logger

php
$builder->setLogger($psrLogger);

Accepts any PSR-3 logger. Defaults to NullLogger (silent). The CLI command sets its own console logger.

Generator configuration (classic mode)

For advanced Generator configuration (custom analysers, processors, aliases, type resolvers), use withGenerator():

php
$builder->withGenerator(function (\OpenApi\Generator $generator) {
    $generator->setAnalyser($customAnalyser);
    $generator->setConfig(['operationId.hash' => false]);
    $generator->withProcessorPipeline(function ($pipeline) {
        $pipeline->remove(\OpenApi\Processors\CleanUnusedComponents::class);
    });
});

The callable receives a pre-configured Generator instance and may either modify it in-place or return a new instance.

Augmenter configuration (spec/hybrid mode) {#augmenters}

For spec and hybrid modes, use withAugmenters() to configure the augmenter pipeline:

php
use OpenApi\Augmenter;

$builder->withAugmenters(function (\OpenApi\Utils\Pipeline $pipeline) {
    // Disable an augmenter
    $pipeline->get(Augmenter\Cleanup::class)?->setEnabled(false);

    // Configure operationId generation
    $pipeline->get(Augmenter\OperationIds::class)?->setHash(true);

    // Filter to specific paths/tags
    $pipeline->get(Augmenter\PathFilter::class)
        ?->setPathFilter('/^\/api\/v2/')
        ?->setTagFilter('/^(Users|Products)$/');

    // Insert a custom augmenter
    $pipeline->insert(new CustomAugmenter(), Augmenter\Inheritance::class);

    // Remove an augmenter entirely
    $pipeline->remove(Augmenter\EnumDescriptions::class);
});

The pipeline is grouped into three phases that run in order: resolvereduceaugment. See the Augmenters reference for the full list and their configuration options.

Attribute factory configuration (spec mode) {#attribute-factory}

Use withAttributeFactory() to add custom attribute translators:

php
use OpenApi\Utils\AttributeFactory;

$builder->withAttributeFactory(function (AttributeFactory $factory): void {
    $factory->getTranslators()->add(new SymfonyValidationTranslator());
});

Translators convert non-OA attributes (e.g. Symfony #[Assert\*], framework route annotations) into spec DTOs during assembly.

Result

The build() method returns a \OpenApi\Builder\Result instance:

php
$result = $builder->build();

$result->isValid();      // bool — true if a spec was generated
$result->toArray();       // array — the spec as a PHP array
$result->toJson();        // string — JSON output
$result->toYaml();        // string — YAML output
$result->files();         // string[] — scanned source files
$result->log();           // array — all log entries [{level, message}, ...]
$result->warnings();      // string[] — warning messages
$result->errors();        // string[] — error messages
$result->specification(); // the final `Specification` instance

Full example (spec mode)

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

$result = (new Builder())
    ->setMode(Mode::SPEC)
    ->setVersion('3.1.0')
    ->addSource('src/Api')
    ->withAugmenters(function (\OpenApi\Utils\Pipeline $pipeline) {
        $pipeline->get(Augmenter\Cleanup::class)?->setEnabled(false);
        $pipeline->get(Augmenter\OperationIds::class)?->setHash(true);
    })
    ->build();

echo $result->toYaml();