fix(doctrine): use PHP property name in DQL for modern filters with name converter#8382
Merged
soyuka merged 1 commit intoJul 3, 2026
Merged
Conversation
…ame converter Modern parameter filters (ExactFilter, SortFilter, ComparisonFilter, PartialSearchFilter) used Parameter::getProperty() verbatim to build DQL/aggregation queries. When a name converter is configured, ParameterResourceMetadataCollectionFactory::setDefaults() normalizes that property (e.g. createdAt -> created_at) for the public/OpenAPI name, but Doctrine still knows the entity field by its PHP name, causing a 500 "has no field or association named created_at" for any multi-word property. Preserve the original PHP property name as a `query_property` extra property before normalizing, and prefer it over the converted property in both NestedPropertyHelperTrait implementations (ORM and ODM), which is the single chokepoint every modern filter routes through for flat (non-nested) properties. Nested properties already skip normalization via nested_properties_info and are unaffected. Follow-up to api-platform#7877, which fixed the equivalent issue for legacy AbstractFilter-based filters. Fixes api-platform#8380
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8380
Problem
Modern parameter filters (
ExactFilter,SortFilter,ComparisonFilter,PartialSearchFilter) useParameter::getProperty()verbatim to build the DQL/aggregation query. When anapi_platform.name_converter(e.g.CamelCaseToSnakeCaseNameConverter) is configured,ParameterResourceMetadataCollectionFactory::setDefaults()normalizes the property (createdAt->created_at) so the public/OpenAPI parameter name matches the API's naming convention. But Doctrine still knows the entity field by its PHP name, so every request filtering/sorting on a multi-word property fails with HTTP 500:Single-word properties (
status,name, ...) are unaffected because camelCase == snake_case for them, which is why the bug is easy to miss.This is a follow-up to #7866 / #7877, which fixed the equivalent problem for the legacy
AbstractFilter-based filters. The docs currently recommend the modern filters as the fix for the legacy filters' name-converter issues, but on this setup they fail harder (500 instead of a silently ignored filter).Fix
The public parameter name and the internal query field name legitimately diverge: the Hydra IRI template mapping and OpenAPI docs read
getProperty()and must expose the converted (created_at) name, while the query must use the PHP field (createdAt).ParameterResourceMetadataCollectionFactory::setDefaults(): before normalizing, stash the original PHP property name as aquery_propertyextra-property on theParameter— only when a name converter runs and there is nonested_properties_info(nested paths already skip normalization and keep their existing handling; the no-name-converter path is untouched).NestedPropertyHelperTrait::addNestedParameterJoins()and ODMNestedPropertyHelperTrait::addNestedParameterLookups(): on the flat (non-nested) return, prefer$extraProperties['query_property'] ?? $property. This is the single chokepoint every modern ORM/ODM filter routes through.ComparisonFilterdelegates to its inner filter (e.g.ExactFilter), so it is covered transitively.Test
New functional test
NameConverterModernFilterTest(ORM + ODM), using the test app's existingCustomConverter(same infra as the #7877NameConverterFilterTest), withQueryParameter(filter: new ExactFilter(), property: 'nameConverted')and aSortFiltercase. Verified it fails before the fix with the exact reportedhas no field or association named name_converted500, and passes after.