fix(php): keep the model namespace for nullable references inside array/map containers

IN
17h ago
+188-42

Fixes #25574

What

When a model reference is made nullable and used inside a container — as an array item or as a map value — the PHP generator now emits the fully qualified class name in $openAPITypes:

  • 'deps' => 'array<string,\OpenAPI\Client\Model\Inner>' (previously 'array<string,\OpenAPIClientModelInner>')
  • 'list_deps' => '\OpenAPI\Client\Model\Inner[]' (previously '\OpenAPIClientModelInner[]')

Why

A nullable reference is represented as a composed schema: oneOf/anyOf with the OAS 3.1 null type, or the OAS 3.0 spelling allOf: [$ref] with nullable: true. After the OpenAPI normalizer simplifies such a schema, it resolves in AbstractPhpCodegen.getSchemaType to a fully qualified model name like \OpenAPI\Client\Model\Inner. That name was then passed through toModelName(), which strips the namespace separators (only the leading backslash survives), so the type written into $openAPITypes pointed at a class that does not exist in the global namespace and ObjectSerializer::deserialize failed on every non-null value.

A plain nullable reference as a regular property was unaffected because fromProperty unwraps a single-member allOf before resolving the type. The inner schema of an array or map container reaches getTypeDeclaration as-is and hit the mangling path, which is why both container shapes were broken.

How

AbstractPhpCodegen.getSchemaType now returns an already fully qualified type (leading backslash) as-is instead of feeding it to toModelName().

Both container shapes are covered by tests in PhpClientCodegenTest:

  • a type-helper test asserting dataType for a nullable reference used as a map value and as an array item
  • an end-to-end test asserting the generated $openAPITypes lines for oneOf/anyOf with the 3.1 null type and for the 3.0 allOf-wrapped spelling, with plain (non-nullable) references as controls

Test spec: modules/openapi-generator/src/test/resources/3_1/php/issue_25574.yaml.

Verification: mvn -pl modules/openapi-generator test is green (5757 tests, 0 failures), checkstyle passes, and regenerating samples/client/petstore/php/OpenAPIClient-php from bin/configs/php-OpenAPIClient.yaml produces no content changes.


Summary by cubic

Fixes the PHP generator emitting broken class names for nullable model references inside arrays and maps, so deserialization no longer fails on non-null values.

The generated $openAPITypes now keeps the fully qualified class name, for example 'deps' => 'array<string,\OpenAPI\Client\Model\Inner>' instead of 'array<string,\OpenAPIClientModelInner>'. Previously, a nullable reference resolved to a qualified model name that toModelName() stripped of namespace separators, producing a type pointing at a non-existent class in the global namespace.

Bug Fixes

  • Returns already qualified types (leading \) as-is in getSchemaType instead of passing them through toModelName().
  • Adds type-helper and end-to-end tests covering oneOf/anyOf with the OAS 3.1 null type and the OAS 3.0 allOf-wrapped spelling, with plain references as controls.
  • Regenerates the echo_api php-nextgen and php-nextgen-streaming samples, whose generated output changed to match the generator.