[php] fix: enumUnknownDefaultCase declares the unknown-default member but never deserializes to it

Merged
WI
21d ago
+23-0

With enumUnknownDefaultCase=true, the php client adds UNKNOWN_DEFAULT_OPEN_API to every enum class, but ObjectSerializer::deserialize still throws for a $ref'd enum. The error message even lists the member it refuses to return:

InvalidArgumentException: Invalid value for enum 'OpenAPI\Client\Model\DomainStatus', must be one of: 'ACTIVE', 'INACTIVE', 'unknown_default_open_api'

#20594 fixed inline enum properties only; a $ref'd enum is its own class and is rejected in ObjectSerializer before any model sees it. Reproduced on current master.

Fix

ObjectSerializer.mustache, the enum branch of deserialize:

{{#enumUnknownDefaultCase}}
if (defined("$class::UNKNOWN_DEFAULT_OPEN_API")) {
    return constant("$class::UNKNOWN_DEFAULT_OPEN_API");
}
{{/enumUnknownDefaultCase}}

The branch is generated only with the flag, and at runtime it applies only to enum classes that declare the constant. Output without the flag is byte-identical.

Verification (php 8, DomainStatus: [ACTIVE, INACTIVE], Domain.status: $ref, flag on)

masterthis PR
deserialize('SOMETHING_NEW', DomainStatus::class)throws InvalidArgumentExceptionreturns 'unknown_default_open_api'
deserialize(payload, Domain::class) with status: "SOMETHING_NEW"throws InvalidArgumentExceptiongetStatus() returns 'unknown_default_open_api'

Tests

The two PhpClientCodegenTest cases from #20594 now also check the generated ObjectSerializer.php: the fallback is present with the flag (fails without the fix) and absent without it.

Known gaps

php-nextgen has the same defect, but its enums are native \BackedEnums, so the fix needs different mechanics and a separate PR.

PR checklist

  • Read the contribution guidelines.
  • Built the project and updated samples (./bin/generate-samples.sh ./bin/configs/php*.yaml). No sample changed: none enables enumUnknownDefaultCase.
  • Technical committee: @jebentier @dkarlovi @mandrean @jfastnacht @ybelenko @renepardon

Summary by cubic

Fixes PHP enum deserialization when enumUnknownDefaultCase is enabled: unrecognized enum values now return the unknown-default member instead of throwing InvalidArgumentException.

  • The fallback in ObjectSerializer::deserialize returns the enum's UNKNOWN_DEFAULT_OPEN_API constant only when that constant is defined, and only in clients generated with the flag; other clients are byte-identical.
  • Adds tests covering both enabled and disabled flag states.

Generated with Claude Code