-
-
Notifications
You must be signed in to change notification settings - Fork 932
Improved recursion handling in EagerLoadingExtension #4377
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
Improved recursion handling in EagerLoadingExtension #4377
Conversation
This is until api-platform/core#4377 is merged, see that PR and api-platform/core#2444 for details.
I like this, please rebase against main if we can merge this it'd be a must |
c73cc65
to
3d48bbb
Compare
@soyuka rebased onto main. We also had to add another commit to make sure each alias is added to the select clause only once. Doctrine would cause nasty errors otherwise. |
The EagerLoadingExtension is only temporarily in our codebase, until api-platform/core#4377 is merged and released. There are tests for this extension in API Platform core, so we shouldn't need to write our own test suite for it. However, because of our limited use cases so far, this class lowers the coverage too much. Therefore, I commented out some code of which I am certain we won't need it in the near future. Less untested code = higher coverage.
This exact select statement is already added a few lines above. The only exception is when fetchPartial is active, and in that case the current implementation is wrong anyways, because it always adds the full select. When this "temporary" solution for avoiding recursion was implemented, the duplicated line above was not yet there: https://github.com/api-platform/core/blob/5ba518014e2770e1ad5686b0124b2db45245fee5/src/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php#L148 But later, the duplicated statement was added, and the select statement inside the "Avoid recursion" case was made obsolete: api-platform@e34427a
3d48bbb
to
4c6ae9e
Compare
Not sure why the Behat Rector installation fails. But given that currently all PRs as well as the main branch have the same error, and I didn't touch anything composer.json-related, I think there is nothing to fix in this PR. |
You're right. I think @soyuka would like to review your PR before merging it. Nice work. |
Thank you very much for the work @carlobeltrame ! |
* feat: Avoid eager joining back to the just visited parent * fix: Remove unnecessary duplicate select statement This exact select statement is already added a few lines above. The only exception is when fetchPartial is active, and in that case the current implementation is wrong anyways, because it always adds the full select. When this "temporary" solution for avoiding recursion was implemented, the duplicated line above was not yet there: https://github.com/api-platform/core/blob/5ba518014e2770e1ad5686b0124b2db45245fee5/src/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php#L148 But later, the duplicated statement was added, and the select statement inside the "Avoid recursion" case was made obsolete: api-platform@e34427a * refactor(eager loading): Avoid joining unnecessary recursive relations * fix: prevent adding same alias twice; doctrine does not like it Co-authored-by: Pirmin Mattmann <pimattmann@gmail.com>
This PR works towards #2444. I refactored the EagerLoadingExtension a bit. Namely I changed 3 things:
author.books
, the nestedjoinRelations(..., Book::class, ...)
call will ignore thebook.author
relation, because we already know the author.readableLink: true
, it should be eager loaded, including it's transitive relations (which are readable etc.). Otherwise, if the relation is at leastreadable: true
, it should still be eager loaded (for generating the IRI), but not its relations. E.g. an author has many books and each book has many chapters. When eager loading the author's relations, we want to eager load the books as soon asauthor.books
isreadable
, but unlessauthor.books
is alsoreadableLink
, we don't need to eager loadbook.chapters
. This PR introduces the ability toaddSelect('books')
without calling the recursive$this->joinRelations(..., 'books', ...)
.Since the implementation of the
joinRelations
method takes into account a lot of options, I visualized the behaviour here. Left is before this PR, right is after. Green is the first commit, red the second, blue the third, where I basically only moved thereadableLink
check later. This move resulted in some more (correct) joins in some Behat tests.editor link for later reference
These changes all don't break backward compatibility because of Doctrine's awesome ability to fetch missing relations when they are accessed.
Motivation
This PR is motivated by our application which uses the following pattern for serialization groups:The idea is that we always want to present full representations in the API, never partial. And we always want to list all relations as links, except in a few cases where we embed them (using a quite elegant mechanism also based on serialization groups).
Unfortunately, with these groups, the current implementation of the EagerLoadingExtension will eager join absolutely everything, running into the join limit very quickly.