-
-
Notifications
You must be signed in to change notification settings - Fork 957
fix(doctrine): fix partial fetch when relation switches context #7645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| $propertyContext = $attributesMetadata[$association]->getDenormalizationContextForGroups((array) $originalGroups); | ||
| $propertyOptions['denormalization_groups'] = $propertyContext[AbstractNormalizer::GROUPS] ?? $originalGroups; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really interesting use case. I'm wondering though if this isn't making unnecessary overhead when there is no context switch. Indeed this runs for every association, what do you think about caching the computed propertyOptions if called multiple times for the same association?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the gain, let me explain why I think that:
- This class is called when building the DQL query (not serializing objects). So once per HTTP request.
- This code should be called once per entity + once per relation - recursively => In most projects, it should be just a bunch of entities
- The call to
getNormalizationContextForGroupsis super light (foreach groups + array_merge) and should be very fast. - Since my last refactoring and early return, this code is not called when the relation does not have context switch
Using a cache will be effective when we need to serialize the same class multiple times for different relations. Which is (IMHO) a rare case.
But if it's true, let's says, a class has hundred of relations of the same class. Then:
- the SQL query will have hundreds of joins
- doctrine will hydrate hundred × N objects (N = number of rows)
- The Symfony Serializer will call similar code hundred × N times
So I think, using cache for this will add complexity for a rare edge case and will not change the overall response time anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this function has performance issue, maybe we should cache (in a persistent storage like redis/filesystem/...) ALL the class's logic instead 🤔
For the same $resourceClass, $operation and $context we collect (and cache) joins and selects, and then we just have to re-apply them on next request.
| ++$joinCount; | ||
| } | ||
|
|
||
| $propertyOptions = $options; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (isset($attributesMetadata[$association])) {
$hasCustomContext = $attributesMetadata[$association]->hasNormalizationContext()
|| $attributesMetadata[$association]->hasDenormalizationContext();
// Early return if no custom context
if (!$hasCustomContext) {but probably move your code to a function to make things more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, I moved code in dedicated method, and early return when no context is defined.
ab5d76b to
d98672a
Compare
|
thanks! |
When an entity has a relation and changes its serialization context (using
#[Context(...)]attribute, the EagerLoadingExtension fails to resolve the partial properties to fetch.reproducer
In that case the
EagerLoadingExtensioniterates over entities that are included in the groupA, therefore does not includeAddress::labelbecause it bellong to the groupB.This PR uses the existing
$attributesMetadataand itsgetNormalizationContextForGroups/getDenormalizationContextForGroupsmethods to update the serialization context when resolving relations.