Skip to content

fix(php): honor OpenAPI default beside $ref in toDefaultValue#23541

Merged
wing328 merged 2 commits intoOpenAPITools:masterfrom
JerrySLau:fix_query_enum_default
Apr 15, 2026
Merged

fix(php): honor OpenAPI default beside $ref in toDefaultValue#23541
wing328 merged 2 commits intoOpenAPITools:masterfrom
JerrySLau:fix_query_enum_default

Conversation

@JerrySLau
Copy link
Copy Markdown
Contributor

@JerrySLau JerrySLau commented Apr 14, 2026

Summary

Optional php-symfony query parameters whose schema is an enum $ref with a sibling default (common under components.parameters) used to get an empty CodegenParameter.defaultValue. api_controller.mustache then emitted $request->query->get('name') without the default argument, so the value stayed null and Assert\Type(<enum>) failed before the handler ran.

Root cause

AbstractPhpCodegen.toDefaultValue(Schema) only handled defaults when ModelUtils classified the schema as boolean / number / integer / string. Schemas that are effectively “$ref + default on the same object” often do not match those branches, so the method returned null even when schema.getDefault() was set.

Fix

After the existing type-specific branches, add a small fallback: if getDefault() != null, emit a PHP literal—String values as single-quoted strings via escapeTextInSingleQuotes, other types via toString(). That fills CodegenParameter.defaultValue, so existing templates emit query->get('<baseName>', <default>) (and related Elvis paths where applicable) without changing Mustache.

Scope: all generators extending AbstractPhpCodegen (client, php-symfony, Slim4, Flight, etc.).

Tests

  • PhpSymfonyServerCodegenTest
    • testOptionalEnumRefQueryParameterWithDefaultAppliesOpenApiSemantics: generates from src/test/resources/3_1/php-symfony/optional-enum-query-ref-default.yaml and asserts the controller contains query->get('tone', …) (or equivalent) alongside the existing limit control case.
    • testPetstoreDottedEnumRefQueryParameterUsesShortClassInApiInterface: assertions updated so that when a default is present, the interface may use a non-nullable PetModelPetStatus $status (consistent with api.mustache when defaultValue is set).
  • Additional PHP regression coverage run locally, e.g. AbstractPhpCodegenTest, PhpClientCodegenTest, PhpModelTest, PhpNextgenClientCodegenTest, PhpFlightServerCodegenTest, PhpSlim4ServerCodegenTest, PhpClientExampleTest, PhpClientOptionsTest, PhpLumenServerOptionsTest.

Issue link

PR checklist


Summary by cubic

Honor OpenAPI defaults when a schema uses $ref with a sibling default, so optional enum query params in php-symfony receive the default and pass validation. Uses safe PHP literals for defaults across generators extending AbstractPhpCodegen.

  • Bug Fixes
    • In AbstractPhpCodegen.toDefaultValue, when schema.getDefault() is set (even with $ref), map it via defaultValueToPhpLiteral to a safe PHP scalar (strings escaped; booleans/numbers handled; unsupported values omitted) and set CodegenParameter.defaultValue.
    • php-symfony now passes defaults to $request->query->get() and uses non-nullable interface type hints/PHPDoc when a default exists, preventing early enum Assert\Type failures.
    • Added optional-enum-query-ref-default.yaml and tightened PhpSymfonyServerCodegenTest to assert non-nullable types and that the controller applies the default.

Written for commit 1fa1b8c. Summary will update on new commits.

Parameter/model schemas that combine $ref with a sibling default were not
handled by the boolean/number/string branches, so CodegenParameter.defaultValue
stayed empty and php-symfony emitted query->get without the second argument.

Add a fallback: when getDefault() is set, emit a PHP literal (quoted strings
via escapeTextInSingleQuotes, other types via toString()).

Update PhpSymfonyServerCodegenTest: assert optional enum-ref query defaults, and
relax petstore interface assertions when a default is present (non-nullable
signature per api.mustache).
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java">

<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java:222">
P3: The interface test was weakened to accept nullable output, so it no longer verifies that a defaulted enum ref is emitted non-nullably.</violation>
</file>

<file name="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java">

<violation number="1" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java:647">
P2: `toDefaultValue` now falls back to `def.toString()` for non-string defaults, which can emit non-PHP literals and break generated PHP code.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…-symfony tests

AbstractPhpCodegen maps getDefault() to valid PHP via defaultValueToPhpLiteral
instead of blind toString(). PhpSymfonyServerCodegenTest asserts non-nullable
handler params when an enum $ref has an OpenAPI default (petstore + optional spec).
@wing328
Copy link
Copy Markdown
Member

wing328 commented Apr 15, 2026

thanks for the PR

test results look good

diff --git a/Api/DefaultApiInterface.php b/Api/DefaultApiInterface.php
index f9659b3..d992eea 100644
--- a/Api/DefaultApiInterface.php
+++ b/Api/DefaultApiInterface.php
@@ -46,7 +46,7 @@ interface DefaultApiInterface
     /**
      * Operation listFeedHints
      *
-     * @param  PetAnnouncementTone|null $tone  Optional filter; default applies when the query key is omitted. (optional)
+     * @param  PetAnnouncementTone $tone  Optional filter; default applies when the query key is omitted. (optional, default to 'friendly')
      * @param  int $limit  Integer optional query with default (often generated correctly). (optional, default to 10)
      * @param  int     &$responseCode    The HTTP Response Code
      * @param  array   $responseHeaders  Additional HTTP headers to return with the response ()
@@ -54,7 +54,7 @@ interface DefaultApiInterface
      * @return void
      */
     public function listFeedHints(
-        ?PetAnnouncementTone $tone,
+        PetAnnouncementTone $tone,
         int $limit,
         int &$responseCode,
         array &$responseHeaders
diff --git a/Controller/DefaultController.php b/Controller/DefaultController.php
index 77ab39e..47ffd8a 100644
--- a/Controller/DefaultController.php
+++ b/Controller/DefaultController.php
@@ -60,7 +60,7 @@ class DefaultController extends Controller
         // Handle authentication

         // Read out all input parameter values into variables
-        $tone = $request->query->get('tone');
+        $tone = $request->query->get('tone', 'friendly');
         $limit = $request->query->get('limit', 10);

@wing328 wing328 merged commit 1680d28 into OpenAPITools:master Apr 15, 2026
14 checks passed
@wing328 wing328 added this to the 7.22.0 milestone Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants