-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
[DoctrineBridge][Form] Introducing new LazyChoiceLoader
class and choice_lazy
option for ChoiceType
#52503
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
ExtraLazyChoiceLoader
class and extra_lazy
option for DoctrineType
ExtraLazyChoiceLoader
class and extra_lazy
option for DoctrineType
ExtraLazyChoiceLoader
class and extra_lazy
option for DoctrineType
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 |
+1 I had a similar case few years ago with an API relying on a Symfony form with an EntityType loading thousands of choices. |
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. |
I'm not sure this |
@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
to
87afdea
Compare
87afdea
to
53463a2
Compare
This comment was marked as off-topic.
This comment was marked as off-topic.
src/Symfony/Component/Form/ChoiceList/Loader/ExtraLazyChoiceLoader.php
Outdated
Show resolved
Hide resolved
53463a2
to
e933246
Compare
e933246
to
33b2f3d
Compare
4016846
to
fae0d67
Compare
src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php
Outdated
Show resolved
Hide resolved
fae0d67
to
2953bcf
Compare
Thanks @xabbuh for your review! I also added two test cases more about |
LazyChoiceLoader
class and choice_lazy
option for ChoiceType
LazyChoiceLoader
class and choice_lazy
option for ChoiceType
2953bcf
to
97ddd62
Compare
Just rebased to fix conflicts. |
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?
@nicolas-grekas this lazy mode assumes that you have a form rendering that does not need the list of available choices (and so not rendering it as a This is the reason why I suggested that it may fit better as a separate form type instead (which would have a separate rendering). Making all choice loaders wrapped in this LazyChoiceLoader in ChoiceType itself would break it. |
97ddd62
to
d73b5ee
Compare
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 🙏 |
You might still want to use a |
This is ready on my side. @stof any blocker on your side? |
Thank you @yceruto. |
This PR was merged into the 7.2 branch. Discussion ---------- [Form] Documenting ``choice_lazy`` option Closes symfony#20311 Code PR * symfony/symfony#52503 Commits ------- e55e7cd documenting choice_lazy option
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
LazyChoiceLoader
class addresses this performance issue by implementing an on-demand choice loading strategy. This class is integrated with anyChoiceType
subtype 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
LazyChoiceLoader
class, which delegates the loading of choices to a wrappedChoiceLoaderInterface
adapter (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, the Autocomplete UX Component now uses this choice loading strategy, simplifying its autocomplete form type to a single field:
A Handy Use Case without Javascript?
The
disabled
option renders anEntityType
form field read-only, and when combined with thechoice_lazy
option, 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!