Skip to content

feat: populate schema required from its properties#2034

Open
alleknalle wants to merge 1 commit into
zircote:masterfrom
alleknalle:feature-auto-required-from-nullable
Open

feat: populate schema required from its properties#2034
alleknalle wants to merge 1 commit into
zircote:masterfrom
alleknalle:feature-auto-required-from-nullable

Conversation

@alleknalle

Copy link
Copy Markdown
Contributor

Adds an AugmentRequired processor: explicit required: true/false always applies, and nullability inference is opt-in via augmentRequired.enabled.

Closes #2017

Summary

Today Schema::required (the array of required property names) has to be maintained separately from the properties it refers to. This adds a new AugmentRequired processor that derives it from the properties themselves, in two layers:

Explicit per-property flag (always on). A property can declare required: true or required: false. true adds its name to the parent Schema::required, false removes it. The boolean is consumed during processing so it never serialises on the property, where required must be an array.

#[OA\Property(property: 'name', type: 'string', required: true)]

Nullability inference (opt-in). With the augmentRequired.enabled config flag (off by default, same shape as cleanUnusedComponents.enabled), a property backed by a PHP member becomes required when it has a known, non-nullable type:

#[OA\Property] public string $name;       // required
#[OA\Property] public ?string $nickname;  // optional

Design notes

  • Explicit wins, inference fills the gaps. An explicit required/nullable value always takes precedence over inference, and an explicitly declared required list on a schema is never modified by inference.
  • **Inference only marks a positively-known he !isNullable() rule used for parametersand request bodies, property scanning also hits untyped/mixed/unresolvable properties; those have no determinable nullability, so they are left optional rather than assumed required.
  • **Inference is scoped to PHP-backed memberomoted parameter, method), so hand-authoredinline schema properties are untouched.
  • Off by default because inference changes output for existing projects that use typed properties; the explicit flag is new syntax and therefore safe to always run.

API change (non-breaking)

The Property attribute's required parameter widens from ?array to bool|array|null. Arrays and null behave exactly as before; only the boolean form is new.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Enhancement (improvement to existing functionality)
  • Breaking change (fix or feature that wlity to change)
  • Documentation update
  • Refactor (no functional changes)
  • Chore (maintenance, dependencies, CI)

Related Issues

Closes #2017

Test Plan

Unit / processor testsAugmentRequiredTest (16 cases) plus fixtures cover: the opt-in flag, non-nullable typed properties (incl. $ref), nullable/untyped/mixed left optional, explicit nullable override, promoted-parameter and
method-backed properties, the reflector gate, explicit true/false adding to andremoving from both empty and declared lists, the boolean being consumed (named and unnamed properties), and an array required on an object property left untouched. The InvalidPropertyAttribute test now passes a string to still
assert the constructor's type error.

Integration test — a ScratchTest fixture (RequiredFromProperties) generates a full spec for a schema with explicit required: true/false properties referenced from a GET endpoint, and compares the serialized YAML across OpenAPI 3.0/3.1/3.2 and both type resolvers. This verifies end-to-end that required: true emits required: [id] on the component and that no required: true leaks onto a property in the output.

Ran locally: full suite (1081 tests), PHPStan, php-cs-fixer, and rector --dry-run all pass.

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code where necessary
  • I have updated the documentation accordingly
  • My changes generate no new warnings
  • New and existing tests pass locally
  • Any dependent changes have been merged and published

Adds an AugmentRequired processor: explicit `required: true`/`false` always applies, and nullability inference is opt-in via `augmentRequired.enabled`.

Closes zircote#2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Automatically populate schema::required from properties that are required

1 participant