Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[DoctrineBridge][Form] Introducing newLazyChoiceLoader class andchoice_lazy option forChoiceType#52503
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
ExtraLazyChoiceLoader class andextra_lazy option forDoctrineTypeExtraLazyChoiceLoader class andextra_lazy option forDoctrineTypeExtraLazyChoiceLoader class andextra_lazy option forDoctrineTypeyceruto commentedNov 8, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Over there, there should be other special use cases, such as using API payloads against forms where the choice lists are not really necessary, so people work around with custom form types and special |
Seb33300 commentedNov 9, 2023
+1 I had a similar case few years ago with an API relying on a Symfony form with an EntityType loading thousands of choices. |
Pixelshaped commentedNov 9, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Thank you I was already using this code from UX Autocomplete and I think it's the right move to make it part of Doctrine Bridge as this is a very common use case, even if part of the solution is front end (one would still need to implement a route to get a paginated list of entities and pass it to Select2 or whatever solution you're using). I had duplicated the ExtraLazyChoiceLoader in my project to not require UX Autocomplete (as I'm using Select2 already everywhere), and now I can use this and stay updated. Nice job. |
stof commentedNov 9, 2023
I'm not sure this |
yceruto commentedNov 9, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@stof certainly there's additional work required to create a fully-autocomplete type, which is not the goal of this PR btw. However, it does streamline implementations that previously needed custom/complex solutions. The I believe the |
4d42789 to87afdeaCompare87afdea to53463a2Compare This comment was marked as off-topic.
This comment was marked as off-topic.
src/Symfony/Component/Form/ChoiceList/Loader/ExtraLazyChoiceLoader.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
53463a2 toe933246Comparee933246 to33b2f3dCompare4016846 tofae0d67Comparesrc/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
fae0d67 to2953bcfCompareyceruto commentedJul 17, 2024
Thanks@xabbuh for your review! I also added two test cases more about |
LazyChoiceLoader class andchoice_lazy option forChoiceTypeLazyChoiceLoader class andchoice_lazy option forChoiceType2953bcf to97ddd62Compareyceruto commentedAug 4, 2024
Just rebased to fix conflicts. |
nicolas-grekas left a comment
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.
Maybe stupid comment: can't we always behave lazily when choice_loader is set and get rid of the option altogether?
stof commentedAug 22, 2024
@nicolas-grekas this lazy mode assumes that you have a form rendering that does not need the list of available choices (and sonot rendering it as a This is the reason why I suggested that it may fit better as aseparate form type instead (which would have a separate rendering). Making all choice loaders wrapped in this LazyChoiceLoader in ChoiceType itself would break it. |
97ddd62 tod73b5eeCompareyceruto commentedAug 23, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I can add that if there is data bound to that field (either default or submitted), it will render the choices as usual, rendering only the selected ones in this case.
I might be missing your point here. Still wondering how it could be different from the current one and why... you can currently have different renderings for the same form type using
Sorry, I'm confused by this comment. Is it related to Nicolas' comment? Otherwise, could you please elaborate 🙏 |
yceruto commentedAug 23, 2024
You might still want to use a |
yceruto commentedOct 3, 2024
This is ready on my side.@stof any blocker on your side? |
nicolas-grekas commentedOct 9, 2024
Thank you@yceruto. |
This PR was merged into the 7.2 branch.Discussion----------[Form] Documenting ``choice_lazy`` optionClosessymfony#20311Code PR*symfony/symfony#52503Commits-------e55e7cd documenting choice_lazy option
Uh oh!
There was an error while loading.Please reload this page.
It's quite usual to work with forms that process large datasets. In Symfony Form + Doctrine ORM, if you define an
EntityType, it typically loads all choices/entities fully into memory, and this can lead to serious performance problems if your entity table contain several hundred or thousands of records.The new
LazyChoiceLoaderclass addresses this performance issue by implementing an on-demand choice loading strategy. This class is integrated with anyChoiceTypesubtype by using a new boolean option namedchoice_lazy, which activates the feature.Basic usage in a Symfony form looks like this:
How does it work?
The loader operates by keeping the choice list empty until values are needed (avoiding unnecessary database queries). When form values are provided or submitted, it retrieves and caches only the necessary choices.
As you can see in the code, all this happens behind the
LazyChoiceLoaderclass, which delegates the loading of choices to a wrappedChoiceLoaderInterfaceadapter (in this case, theDoctrineChoiceLoader).Frontend Considerations
Certainly, you may need a JavaScript component for dynamically loading
<select>options, aka autocomplete plugins. You'll need to develop the endpoint/controller to fetch this data on your own, ensuring it corresponds to the form field data source. This aspect is not included in this project.As a point of reference, theAutocomplete UX Component now uses this choice loading strategy, simplifying its autocomplete form type to a single field:
A Handy Use Case without Javascript?
The
disabledoption renders anEntityTypeform field read-only, and when combined with thechoice_lazyoption, it prevents the loading of unnecessary entities in your choice list (only the pre-selected entities will be loaded), thereby enhancing performance.Hope this helps to create simpler autocomplete components for Symfony forms.
Cheers!