[8.x] Add Builder@lazy()
and Builder@lazyById()
methods
#36699
Merged
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.
Background
For querying large datasets, the
Builder
currently has thecursor()
method, which returns aLazyCollection
. This uses less memory than a regularCollection
(returned from theget()
method), since it never keeps more than a single Eloquent model in memory.However, the
cursor()
method still has several drawbacks:It's not truly lazy, since PHP still caches all query results in its buffer.
Turning off buffering introduces its own set of challenges (namely not being able to execute other queries simultaneously).
It cannot eager load relationships, since it only ever deals with a single record at a time.
Depending on the DB, opening a cursor to a huge dataset may have a slight delay vs. running a query with a
LIMIT
.We also have the
chunk()
method, which is kinda lazy, but with a clunky API — as is evident by the fact that we needed to introduce separateeach()
andchunkMap()
methods (withchunkMap()
having to build up the whole result set in memory 🙈).Introducing
lazy()
The new
lazy()
method introduced in this PR will chunk results behind the scenes, and return a singleLazyCollection
of results:Since it's a lazy collection, you have the full power of collections at your fingertips:
You can call
each()
directly on it:You can call
map()
on it:Or even
chunk()
it... The possibilities are endless, and we'll no longer have to create all of these separate one-off methods to query and manipulate results lazily.