fix(metadata): :property dedup drops repeated parameters#8196
Merged
soyuka merged 1 commit intoMay 22, 2026
Merged
Conversation
Multiple `#[QueryParameter(key: ':property', ...)]` attributes with disjoint properties lists were silently overwritten by the last one in `Parameters::add`, `Parameters::__construct` and `MetadataCollectionFactoryTrait::mergeOperationParameters`. The `getProperties()` cache in `ParameterResourceMetadataCollectionFactory` also collided on shared key. `:property` keys are templates expanded per-property later, so multiple templates with disjoint `properties` must coexist. Templates with identical `properties` keep last-write-wins semantics. Closes api-platform#8184
c43fc5b to
5d51ad9
Compare
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.
Summary
Multiple
#[QueryParameter(key: ':property', ...)]class-level attributes with disjointpropertieslists were silently collapsed to the last attribute. Same key, different filter per property was unreachable without awkward namespacing (exact[:property],partial[:property]).Example
Before this fix only the second attribute survived; after the fix all four properties resolve to their declared filters.
Why
Parameters::add(),Parameters::__construct(), andMetadataCollectionFactoryTrait::mergeOperationParameters()deduplicated by(class, key)before the:propertyplaceholder was expanded.ParameterResourceMetadataCollectionFactory::getProperties()cache key was also shared between disjoint templates.:propertyis a template, not a final key — it expands per-property inParameterResourceMetadataCollectionFactory::getDefaultParameters. Two templates with disjointpropertieslists must coexist; the final per-property keys are concrete and dedup normally.What changed
Parameters::add/Parameters::__construct: when key contains:property, the storage key includes a discriminator built from the parameter'sproperties(orproperty) list. Deterministic, cache-safe.MetadataCollectionFactoryTrait::mergeOperationParameters: skip thehas()short-circuit for:propertytemplated keys.ParameterResourceMetadataCollectionFactory::getProperties: includepropertieslist in the local cache key.Templates with identical
propertieskeep last-write-wins (intentional override).Tests
Metadata\Tests\ParametersTest: two new tests cover constructor andadd()paths.Metadata\Tests\Resource\Factory\ParameterResourceMetadataCollectionFactoryTest::testRepeatedPropertyPlaceholderAttributesExpandPerPropertyFilter: end-to-end factory expansion verifying each property receives its declared filter.Related
#7870 (per-property
Parameterattributes viaTARGET_PROPERTY) provides a complementary, cleaner declaration model for the original use case in #8184 once it lands.