4.2 KiB
swagger-php
A PHP library that generates OpenAPI specification documents from PHP source code by scanning annotations (attributes and docblocks) and processing them into a complete spec.
Language
Core Concepts
Annotation: An OpenAPI specification element declared as a PHP 8+ attribute or legacy docblock comment on a class, method, or property. Avoid: Attribute (too narrow), decorator, metadata
Analysis: The aggregate result of scanning source code — contains all discovered annotations and structural definitions, before processing. Avoid: Result, scan output
Context: Nested metadata describing where an annotation was found in the source hierarchy (file, namespace, class, method, property). Avoid: Location, position
Generator: The orchestrator that coordinates scanning, processing, and output — it generates an OpenAPI spec from annotations, not code from a spec. Avoid: Builder, compiler
Processor: A single transformation step in an ordered pipeline that converts raw Analysis into a valid, complete OpenAPI specification. Avoid: Handler, middleware, transformer
Annotation Lifecycle
Unmerged: An annotation that has been discovered but not yet incorporated into the target OpenAPI root object. Avoid: Pending, orphaned
Merge: Incorporating an annotation into its correct position within the OpenAPI object tree, guided by the nesting map. Avoid: Combine, attach
Augment: Filling in missing annotation fields with values inferred from code (e.g. deriving a schema type from a PHP type hint). Avoid: Enrich, hydrate
Expand: Resolving PHP inheritance (classes, interfaces, traits, enums) by copying parent annotations into child schemas. Avoid: Inherit, flatten
Structural Concepts
Nesting:
The declarative parent-child mapping ($_nested) that defines which annotation types can belong inside other annotation types — distinct from PHP class inheritance.
Avoid: Hierarchy (ambiguous with class hierarchy)
Component:
A reusable named definition stored in #/components/ and referenced via $ref elsewhere in the spec.
Avoid: Shared schema, template
Ref:
A JSON Pointer ($ref) linking to another part of the spec, resolved by processors into #/components/... paths.
Avoid: Link (means something else in OpenAPI), pointer
Scanning
Analyser: Reflects on PHP source files to discover annotations and produce an Analysis. Avoid: Scanner (too narrow — TokenScanner is a sub-component), parser
AnnotationFactory: Creates annotation objects from discovered PHP attributes or docblock comments during analysis. Avoid: Builder, constructor
Relationships
- A Generator uses an Analyser to produce an Analysis
- An Analysis contains Annotations, each carrying a Context
- Processors run sequentially on an Analysis, first merging unmerged annotations, then expanding inheritance, then augmenting missing fields
- Nesting defines where an Annotation can be merged within the OpenAPI tree
- A Component is an Annotation that has been merged into
#/components/and is reachable by Ref
Example dialogue
Dev: "I added a
@OA\Schemaon a class but it's not appearing in the output." Domain expert: "Is it still unmerged? Check that the nesting map allows it to be merged into Components, and that a processor hasn't filtered it out."
Dev: "Why does the child class schema include the parent's properties?" Domain expert: "That's expansion — the ExpandClasses processor copies parent annotations into the child during the pipeline."
Flagged ambiguities
- "generate" — resolved: reserve for the full end-to-end pipeline (
Generator::generate()). Use analyse for the discovery phase and serialize for producing JSON/YAML output. - "merge" — resolved: reserve for tree-placement (moving an annotation into its correct position in the OpenAPI object). Combining multiple annotations' fields into one (e.g. Properties into a Schema) is part of augment.
- "nested" — resolved: use nesting map when referring to the
$_nesteddeclaration. Use enclosing when talking about the physical source code structure (file, class, method) that Context tracks.